# How to plot a complicated multi-variable function in a tex document automatically, not just importing an image

I have the following Tex functions and I want to plot them in my tex thesis, but I don't know how. I mean, I want the Tex to draw the function, not just to include an external image to it.

y[\text{x$\_$},\text{m$\_$},\text{n$\_$}]\text{:=}\text{Abs}\left[1-\left(1-\left(\frac{x+1}{2}\right)^2\right){}^{\wedge}m\right]{}^{\wedge}n;

\text{F}[\text{x$\_$},\text{m$\_$},\text{n$\_$}]\text{:=}(-y[0,m,n]+(y[0,m,n]-1)x+y[x,m,n])/(1-2y[0,m,n])

\text{Plot}[\{\text{F}[x,0.2,0.5],\text{F}[x,1,5],\text{F}[x,1,10]\},\{x,-1,1\}]

• 3 variables function! Would not be easy! – Sigur Jul 28 '14 at 21:40
• Check out the pgfplots package. – Martin Heller Jul 28 '14 at 22:11
• Could you show the output of the Mathematica code? – Jake Jul 29 '14 at 5:35

## 5 Answers

Here is a solution by means of pgfplots + lualatex (i.e. it has to be compiled with lualatex P.tex:

\documentclass{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
\begin{tikzpicture}
\directlua{
Y = function(x,m,n)
return math.abs(1-(1-((x+1)/2)^2)^m)^n
end
N1 = function(x,m,n)
return (-Y(0,m,n) + (Y(0,m,n)-1)*x + Y(x,m,n))/ (1-2*Y(0,m,n))
end
}
\pgfmathdeclarefunction{N1}{3}{%
\edef\pgfmathresult{\directlua{tex.print(N1(\pgfmathfloatvalueof{#1},\pgfmathfloatvalueof{#2},\pgfmathfloatvalueof{#3}))}}%
}%
\begin{axis}[
axis lines=center,
enlargelimits,
tick align=inside,
no markers,
legend entries={$N1(x,0.2,0.5)$\\$N1(x,1,5)$\\$N1(x,1,10)$\\},
domain=-1:0.99999,
samples=150,
minor tick num=4,
]
\addplot {N1(x,0.2,0.5)};
\addplot {N1(x,1,5)};
\addplot {N1(x,1,10)};
\end{axis}
\end{tikzpicture}
\end{document}


some remarks:

• I have used LUA in order to benefit from its higher accuracy - the current formulation of N1 suffers from numerical instability near x=-1 (i.e. small errors in the input add up to huge errors in the output). This requires higher precision than TeX offers by means of its builtin methods.
• I ignored the possibility to reuse the value for y(0,m,n). It does not hurt to compute it twice.
• Add cycle list={dashed,black,black} to the option list of the axis to get your plot styles - I prefered the defaylt cycle list (with no markers) such that you can identify each in a legend (which I added as well).
• Note that I chose to define a PGF math function N1 by means of \pgfmathdeclarefunction. This allows us to use N1(x,m,n) inside of a PGF math expression (in particular: in \addplot {<expression>}). The argument {3} means that the new function takes three arguments, available as #1, #2, and #3 as in a macro. Currently, these arguments are in some internal format generated by the floating point library (in TeX), so we need to convert them back to something understood by LUA (by means of \pgfmathfloatvalueof.
• since I never plotted Y directly, I did not generate a \pgfmathdeclarefunction for Y -- after all, the LUA code can compute this in a self-contained fashion.
• Note that \pgfmathdeclarefunction is supposed to assign results to the macro \pgfmathresult, which is the purpose of \edef\pgfmathresult. The tex.print is LUA's way to report results back to TeX.

In general, it would be safe to formulate the function by means of PGF's math engine which results in

\documentclass{standalone}

\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
\begin{tikzpicture}
\pgfmathdeclarefunction{Y}{3}{%
\pgfmathparse{abs(1-(1-((#1+1)/2)^2)^(#2))^(#3)}%
}%
\pgfmathdeclarefunction{N1}{3}{%
\pgfmathparse{(-Y(0,#2,#3) + (Y(0,#2,#3)-1)*(#1) + Y(#1,#2,#3))/ (1-2*Y(0,#2,#3)}%
}%
\begin{axis}[
axis lines=center,
enlargelimits,
tick align=inside,
no markers,
legend entries={$N1(x,0.2,0.5)$\\$N1(x,1,5)$\\$N1(x,1,10)$\\},
domain=-1:0.99999,
samples=150,
minor tick num=4,
]
\addplot {N1(x,0.2,0.5)};
\addplot {N1(x,1,5)};
\addplot {N1(x,1,10)};
\end{axis}
\end{tikzpicture}
\end{document}


Note the visible artifact near x=-1; it originates in the numerically instable function formulation near x=-1 combined with TeX's limited precision (unless I am mistaken).

• Is there any way to understand why this instability exists? – Enthusiastic Engineer Jul 29 '14 at 18:58
• My hypothesis is based on the differences computed in y(x,m,n). For x=-1, y=0. Near x=-1, it is approximately 0. In this regime, parts of N1 cancel out (at least almost entirely). My guess is that in the presence of inaccuracies, these inaccuracies do not cancel out as they should. They are magnified. But I did not proof it (and I hope that I did not claim something stupid. Let me know if you proof me wrong). I know that TeX's precision is somewhat less than float, so this sounds plausible. – Christian Feuersänger Jul 29 '14 at 19:19
• I am a little in doubt about that because in other outputs and plots, this is not seen (even outputs from other softwares). However, I think that for some m and n, this instability may occur. I will ask my advisor about this. – Enthusiastic Engineer Jul 29 '14 at 19:23
• I would appreciate that effort. Maybe we can improve the PGF math layer as a consequence. – Christian Feuersänger Jul 29 '14 at 19:40
• If you encounter difficulties with my hints, you are welcome to ask new following-up questions of sorts "pgfplots: how can I position legends here/there/whatever". – Christian Feuersänger Jul 30 '14 at 9:41

You can use gnuplot to plot these. For instance, you can use the following code:

\documentclass{standalone}
\makeatletter\newwrite\verbatim@out\makeatother
\usepackage{gnuplottex}
\usepackage{epstopdf}

\begin{document}
\begin{gnuplot}[terminal=epslatex]
set samples 2000 # Set to get more accurate, but slower
set parametric
set xtics -1,.5,1
set ytics -1,.5,1

set trange [-1:1] # Parametric plot range
set xrange [-1.1:1.1] # Axis range

set zeroaxis
set border 0
set xtics axis
set ytics axis

y(x,m,n) = (abs(1-(1-((x+1)/2)**2)**m))**n
N(x,m,n) = (-y(0,m,n) + (y(0,m,n) - 1)*x + y(x,m,n))/(1 - 2*y(0,m,n))

plot t,N(t,0.2,0.5) title "", t,N(t,1,5) title "", t,N(t,1,10) title ""
\end{gnuplot}
\end{document}


You need to compile it with the --shell-escape option, and have gnuplot installed.

As you can see in the code, it is easy to define and use functions in gnuplot, even with multiple parameters.

Rendering:

• can you mark each graph on itself? – Enthusiastic Engineer Jul 29 '14 at 13:06
• how should I render it? I have gnuplot installed on my windows. (sorry if my questions are too basic) – Enthusiastic Engineer Jul 29 '14 at 13:10
• You can have a look at this answer to get gnuplottex working on Windows. – TonioElGringo Jul 29 '14 at 13:25
• I read that question, but I am using texlive, I used the --shell-scape command, but I couldnot render that graph. – Enthusiastic Engineer Jul 29 '14 at 14:30

* Edit * Added dashed patterns, legend and a couple of labels; also an array mn[] of (m,n) pairs is used to create a function N1(m,n)(x) instead of the array of functions.

% f.tex:
%
\documentclass{article}
\usepackage[inline]{asymptote}
\usepackage{lmodern}
\begin{document}
\begin{figure}
\centering
\begin{asy}[width=8cm]
size(9cm);
import graph;
import fontsize;
defaultpen(fontsize(9pt));

pen dashed=linetype(new real[] {4,4});
pen longdashed=linetype(new real[] {12,4});
pen dotted=linetype(new real[] {0,3});

pen[] fpen={
gray+longdashed,
black+dotted,
black+dashed
};

real y(real x,real m,real n){
return abs(1-(1-((x+1)/2)^2)^m)^n;
}

typedef real Func(real);

Func N1(real m,real n){
return
new real(real x){
return (-y(0,m,n)+(y(0,m,n)-1)*x+y(x,m,n))/(1-2y(0,m,n));
};
}

pair[] mn={(0.2,0.5),(1,5), (1,10)};

real xmin=-1, xmax=1;

xaxis(xmin,xmax,LeftTicks(Label(LeftSide),Step=0.5,step=0.1,OmitTick(0)));
yaxis(RightTicks(Step=0.5,step=0.1,OmitTick(0)));

real penwidth=1bp;
real m,n;
for(int i=0;i<mn.length;++i){
m=mn[i].x; n=mn[i].y;
draw(graph(N1(m,n),xmin,xmax,n=400),fpen[i]+penwidth
,legend="$N_1("+string(m)+","+string(n)+")$"
);
}

label("$x$",1.1*(xmax,0),S); // 1.1*(xmax,0) is a location,
// alignment S == (0,-1)  means "South"
m=mn[2].x; n=mn[2].y;

label("$("+string(m)+","+string(n)+")$",
(0.6,N1(m,n)(0.6))
,SW
);

add(
legend(linelength=0.5legendlinelength,nullpen) // here nullpen means no frame
,point(NE),SW,UnFill
);
\end{asy}
\caption{Family of functions $N_1(x,m,n)$}
\end{figure}
\end{document}


Process it as follows:

pdflatex f.tex
asy f-*.asy
pdflatex f.tex


* ======== first version ======== *

Plotting of such families of functions is straightforward with the Asymptote (which is part of the TeXLive distribution for quite a while). Inside the asy environment, the function N1(m,n) uses parameters m and 'n' to create a new real-valued function which takes one real argument. All functions that have to be plotted are collected in array f[] and then plotted inside a loop, using a prepared array of pens fpen[].

% f.tex:
%
\documentclass{article}
\usepackage[inline]{asymptote}
\usepackage{lmodern}
\begin{document}
\begin{figure}
\centering
\begin{asy}[width=7cm]
import graph;
import fontsize;
defaultpen(fontsize(9pt));
pen dashed=linetype(new real[] {4,4});

pen[] fpen={
deepblue+dashed,
black,
orange
};

real y(real x,real m,real n){
return abs(1-(1-((x+1)/2)^2)^m)^n;
}

typedef real Func(real);

Func N1(real m,real n){
return
new real(real x){
return (-y(0,m,n)+(y(0,m,n)-1)*x+y(x,m,n))/(1-2y(0,m,n));
};
}

Func[] f={ N1(0.2,0.5), N1(1,5), N1(1,10) };

real xmin=-1, xmax=1;

xaxis(xmin,xmax,LeftTicks(Label(LeftSide),Step=0.5,step=0.1,OmitTick(0)));
yaxis(RightTicks(Step=0.5,step=0.1,OmitTick(0)));

real penwidth=1bp;
for(int i=0;i<f.length;++i){
draw(graph(f[i],xmin,xmax),fpen[i]+penwidth);
}
\end{asy}
\caption{Family of functions $N_1(x,m,n)$}
\end{figure}
\end{document}


Process it as follows:

pdflatex f.tex
asy f-*.asy
pdflatex f.tex


P.S. I hope you don't count the step asy f-*.asy as too much of extra work.

• Sorry, I am very new to latex. Could you please help me with that process? I do not know how should I use your code. (I am really sorry if my questions are basic.) – Enthusiastic Engineer Jul 29 '14 at 17:02
• @Parsa: Well, welcome to a new beautiful world of wanders. You said you are using texlive. It's a big system, and if it was installed properly, then the two commands, pdflatex and asy should be available to run from the command line (you really need to get familiar with the command line to use TeXLive tools efficiently). As for how to use the code from above: it is just a normal LaTeX document, save it into a plain text file, for example f.tex and process it as instructed. – g.kov Jul 29 '14 at 17:31
• Thank you so much. I processed the plot and it worked indeed. I copied the TeX file, opened the TeXLive command and went to the directory of the TeX file and processed those three commands. No I have the plot. – Enthusiastic Engineer Jul 29 '14 at 19:03
• I have two questions, How should I make those lines dashed, dotted, etc. Because my thesis is not color printed and I have to use those styles. and also, the PDF output is an A4 with lots of margins, how should I reduce those margins to easily include them in my main TeX file? and how should I label the axises? – Enthusiastic Engineer Jul 29 '14 at 19:05
• An also how to label each line in that plot. something like legend or label on each line. – Enthusiastic Engineer Jul 29 '14 at 19:13

Just for fun with PSTricks. Compile it with pdflatex -shell-escape filename.tex twice.

% filename.tex
\documentclass[12pt]{article}

\usepackage{filecontents}
\begin{filecontents*}{graph.tex}
\documentclass[pstricks,12pt]{standalone}
\usepackage{pst-plot}
\usepackage{fourier}

\def\y[#1,#2,#3]{(abs(1-(1-((#1+1)/2)^2)^#2)^#3)}
\def\N[#1,#2,#3]{(-\y[0,#2,#3]+(\y[0,#2,#3]-1)*(#1)+\y[#1,#2,#3])/(1-2*\y[0,#2,#3])}
\psset
{
algebraic,
plotpoints=500,
llx=-15pt,
lly=-15pt,
urx=15pt,
ury=15pt,
xAxisLabel=$x$,
yAxisLabel=$y$,
subticks=10,
subtickcolor=red,
}

\begin{document}
\pslegend[lt]
{
\color{red}\rule{2cm}{2pt}      & \color{red} $N[x,0.2,0.5]$\\
\color{green}\rule{2cm}{2pt}    & \color{green} $N[x,1,5]$\\
\color{blue}\rule{2cm}{2pt}     & \color{blue} $N[x,1,10]$
}
\begin{psgraph}[axespos=top,Dx=0.5,Dy=0.5](0,0)(-1.5,-0.75)(1.5,1.5){12cm}{!}
\foreach \am/\wn/\cl in {0.2/0.5/red,1/5/green,1/10/blue}{\psplot[linecolor=\cl,yMaxValue=6]{-1}{1}{\N[x,\am,\wn]}}
\end{psgraph}
\end{document}
\end{filecontents*}

\immediate\write18{latex graph && dvips graph && ps2pdf -dNOSAFER -dAutoRotatePages=/None graph.ps}

\usepackage{fourier}
\usepackage{graphicx}
\usepackage{lipsum}

\begin{document}
\lipsum[1]
\begin{figure}[hbtp]
\centering
\includegraphics[scale=1]{graph}%
\caption{This is the family of mine $N[x,m,n]$.}
\label{fig:plot}
\end{figure}
See my plot on page~\pageref{fig:plot}
\end{document}


Based on an answer to this question, I renderred my plot as follows (Thanks to Christian Feuersänger). I chose this answer because it was easy for me as a basic user of the LaTeX and it was easier for me tounderstand the process, functions, codes, etc. Also, it is capable of defining different functions and customizable indeed.

\documentclass[varwidth=true, border=10pt, convert={size=640x}]{standalone}
\usepackage{blindtext}

\usepackage{pgfplots}
\pgfplotsset{compat=1.9}

\begin{document}
\begin{tikzpicture}
\directlua{
Y = function(x,m,n)
return math.abs(1-(1-((x+1)/2)^2)^m)^n
end
N1 = function(x,m,n)
return (-Y(0,m,n) + (Y(0,m,n)-1)*x + Y(x,m,n))/ (1-2*Y(0,m,n))
end
}
\pgfmathdeclarefunction{N1}{3}{%
\edef\pgfmathresult{\directlua{tex.print(N1(\pgfmathfloatvalueof{#1},\pgfmathfloatvalueof{#2},\pgfmathfloatvalueof{#3}))}}%
}%
\begin{axis}
[
grid=major,
axis lines=center,
enlargelimits,
tick align=inside,
cycle list ={solid,dotted,dashed},
legend style={at={(0.5,-0.05)},
anchor=north,legend columns=-1},
legend entries={$m=1,n=1$\\$m=1,n=5$\\$m=1,n=10$\\},
domain=-1:0.99999,
samples=200,
minor tick num=5,
xlabel=$x$,
ylabel=$N_{AG - 3}^{\left( 1 \right)}$
]

\addplot {N1(x,1,1)};
\addplot {N1(x,1,5)};
\addplot {N1(x,1,10)};
\end{axis}
\end{tikzpicture}
\end{document}