2

I'm using TikZ to plot several things (geometric surfaces, line plots, etc.) in just one environment. These plots depend on several constants that I define in the same tikzpicture environment. This is a (dummy) example:

\begin{tikzpicture}
\def\a{1}
\def\g{0.5}
\def\kamax{5}
\def\M{15}
\def\T{3}

\pgfmathsetmacro{\Ra}{1 + \a*\M^(1-\g)/\kamax}
\pgfmathsetmacro{\Rb}{1 + \a*\M^(1-\g)/(4*\kamax)}
\pgfmathsetmacro{\la}{\M/(2*\T*\Ra)}
\pgfmathsetmacro{\lb}{\M/(2*\T*\Rb)}

\begin{axis}[domain=0:\M/\T, xlabel = Rate of consumption, ylabel = Time of purchase, title = Optimal time to purchase, legend pos=north west, axis equal image]
\addplot[color=blue][domain=0:\la] {0};
\addplot[color=blue][domain=\la:\lb] {2*\T - (sqrt(2*\a*\kamax*\M^(1+\g)*\T*\x*(\M-2*\T*\x)))/(\a*\M*\x)};
\addplot[color=blue][domain=\lb:\M/\T] {\T};
\addplot[color=red] coordinates {(\la,0)(\la,\T)};
\addplot[color=red] coordinates {(\lb,0)(\lb,\T)};
\end{axis}
\end{tikzpicture}

In the example, the constants defined with \def are the "essential" constants of the problem I'm studying, and those defined with \pgfmathsetmacro are needed to make the plotting easier.

After plotting the example exposed before, I would like to change some of the values of the "essential" constants and plot the same five plots again (in the same environment) to compare results. My question is: is there a way to create macro or function that takes as input my "essential" constants and returns as output the other constants?

My objective is purely to simplify the .tex reading; if I redefine the constants in the same environment after plotting the .tex compiles just fine.

Thank you very much in advance.

  • 1
    Welcome to TeX.SX! Can you please expand the code snippet that you have posted to a full minimal working example. A MWE should compile and be as small as possible to demonstrate your problem. it's much easier to help you if we have full working code to start from. – Andrew May 8 '17 at 23:05
  • Put the calls to \pgfmathsetmacro in a macro (via \newcommand) and call this macro when you have change your "essential" constants. – Paul Gaborit May 8 '17 at 23:09
  • You have 5 plots in your example, but they are not really 'plotting again'. They are plotting different things .... – cfr May 8 '17 at 23:10
  • I edited both the MWE and the question, clarifying what I wanted to do. – Ignacio Correa May 9 '17 at 0:10
5

You can just pack the code into a macro like this

\newcommand*{\a}{}
\newcommand*{\g}{}
\newcommand*{\kamax}{}
\newcommand*{\M}{}
\newcommand*{\T}{}
\newcommand*{\SetupPlot}[5]{%
    \renewcommand*{\a}{#1}%
    \renewcommand*{\g}{#2}%
    \renewcommand*{\kamax}{#3}%
    \renewcommand*{\M}{#4}%
    \renewcommand*{\T}{#5}%
    \pgfmathsetmacro{\Ra}{1 + \a*\M^(1-\g)/\kamax}%
    \pgfmathsetmacro{\Rb}{1 + \a*\M^(1-\g)/(4*\kamax)}%
    \pgfmathsetmacro{\la}{\M/(2*\T*\Ra)}%
    \pgfmathsetmacro{\lb}{\M/(2*\T*\Rb)}%
}

The first lines just make sure the macors are not yet defined. You get an error message otherwise. \def will just overwrite the macros.

You can then write

\SetupPlot{1}{0.5}{5}{15}{3}

Edit: I added % at the end of the lines in the definition of \SetupPlot, because, as cfr pointed out, if you use this macro outside a tikzpicture it will produce unwanted space without the %.

  • Not much point commenting the space at the beginning if you don't comment the rest. – cfr May 8 '17 at 23:17
  • @cfr you are right of course, but I got so accoustomed to this one (a lot of trouble in the past), I only start thinking about commenting spaces in the second line of a macro. And to my knowledge, inside TikZ it's not necessary. – Mike May 8 '17 at 23:25
  • The thing is that you macro doesn't have to be used inside a tikzpicture. I might use it to configure default settings outside such an environment. – cfr May 8 '17 at 23:44
  • @cfr you are right again. – Mike May 8 '17 at 23:52
  • Thank you very much, this worked just fine. I'll mark this answer as accepted. – Ignacio Correa May 9 '17 at 13:56
4

You can use pgf/tikz keys to automatically set your variables. Since you are using tikz you might as well use \tikzset. All that you need to do is do define a key with a code handler and then have the code handler set all of your variables.

Here is one way to do this (as cfr says in the comments, the choice of variable names used here, following the OP, is unwise):

\documentclass{article}
\usepackage{tikz}
\usepackage{etoolbox}% only for \csuse in the MWE
\begin{document}

\tikzset{mysettings/.code n args={5}{% 5 arguments: \a, \g, \kamax, \M and \T
    \def\a{#1}% set the variables
    \def\g{#2}
    \def\kamax{#3}
    \def\M{#4}
    \def\T{#5}
    \pgfmathsetmacro{\Ra}{1 + \a*\M^(1-\g)/\kamax}
    \pgfmathsetmacro{\Rb}{1 + \a*\M^(1-\g)/(4*\kamax)}
    \pgfmathsetmacro{\la}{\M/(2*\T*\Ra)}
    \pgfmathsetmacro{\lb}{\M/(2*\T*\Rb)}
  }
}

\tikzset{mysettings={1}{0.5}{5}{15}{3}}
\foreach \var [count=\y]in {a,g,kamax,M,T,Ra,Rb,la,lb} {
  \var = \csuse{\var};
}

\tikzset{mysettings={2}{0.2}{1}{10}{-3}}
\foreach \var [count=\y]in {a,g,kamax,M,T,Ra,Rb,la,lb} {
  \var = \csuse{\var};
}

\end{document}

So I have defined the tikz key mysettings to take five arguments, corresponding to your parameters \a, \g, \kamax, \M and \T in this order. Passing these parameters to mysettings sets these five variables and, in addition, sets \Ra, \Rb, \la and \lb.

The for-loops at the end of the MWe are just to show that it works. The MWE produces:

enter image description here

Two more comments. You can also set your variables at the start of a tikzicture environment:

\begin{tikzpicture}[mysettings={1}{0.5}{5}{15}{3}]
....
\end{tikzpicture}

Rather than using \def in the definition of mysettings you might want to use \gdef in order to make the definitions "global". On the other hand, the code above makes then local which might be better in your use-case. As cfr says in the comments, this needs to be used with care.

  • It is extremely dangerous to use \gdef with these kinds of macro names. Please do not recommend this. – cfr May 8 '17 at 23:16
  • Following your advice would, for example, override LaTeX's definition of \a globally (\a: macro:#1->\expandafter \@changed@cmd \csname \string #1\endcsname \relax) `. Are you sure that's wise? – cfr May 8 '17 at 23:21
  • 1
    @cfr It is true the macro names may break something but if this is the case then they will almost certainly break with \def, so \gdef is unlikely to cause more harm. Variable names always need to chosen with care and if the OP wants to use these who am I to say that they shouldn't? – Andrew May 8 '17 at 23:23
  • The point is that the \defs are local to the tikzpicture. \gdefs will affect the whole document. So you are much more likely to break something with \gdef. – cfr May 8 '17 at 23:24
  • @cfr Yes, I agree, and that's exactly the point that I made in my post (global versus local) -- which, incidentally, does recommend using \def. I was giving the OP more information so that they would know what to do in the event they needed global variable. I am certainly not endorsing their choice of variable names. I think that it is good that you given additional information that they need to be careful with their variable names. – Andrew May 8 '17 at 23:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.