7

Why does setting the value of key alpha=0.5 inside semilogxaxis options (i.e. \begin{semilogxaxis}[alph=0.5]) not take effect

\documentclass{article}
\usepackage{pgfplots} 

\begin{document}

    \pgfkeys{/tikz/.cd,
        alph/.store in=\alph,
        alph=1
    }

    \begin{tikzpicture}[declare function = { CFDfixedalph(\time) = \time^(\alph-1);}]
    \begin{semilogxaxis}[alph=0.5]
    \addplot[domain = 1e-6 : 1e6, samples = 100] {CFDfixedalph(x)};
    \end{semilogxaxis}
    \end{tikzpicture}

\end{document}

enter image description here

unlike setting the value inside tikzpicture options (i.e. \begin{tikzpicture}[declare function = { CFDfixedalph(\time) = \time^(\alph-1);},alph=0.5])?

enter image description here

10

I'll rename your \alph macro to \alphstore because I am a coward and fear that redefining LaTeX's \alph command, even locally, might have undesirable side effects in some cases.

Background and analysis

pgfkeys implements namespaces1 using its filesystem-like key hierarchy. When you use a package based on pgfkeys (e.g., tikz, pgfplots, forest, tikz-cd, tcolorbox...) and pass a key to a command or environment of this package without specifying the full path of the key, it is typically looked for using a default path for the package. For tikz, the default path is /tikz; for forest, /forest; for tikz-cd, /tikz/commutative diagrams; for tcolorbox, /tcb; and for pgfplots, it is /pgfplots.

Your code:

\pgfkeys{/tikz/.cd,
  alph/.store in=\alphstore,
  alph=1
}

defines and calls the key /tikz/alph because of the /tikz/.cd.2 When you do:

\begin{tikzpicture}[declare function = { ... }, alph=0.5]

alph=0.5 is processed by a command obtained from \begin{tikzpicture}. This is a TikZ command, therefore since your key alph isn't given with a full path, it is looked for in /tikz. In other words, the full path becomes /tikz/alph. This is the key you have defined, thus it can be run without any problem. However, when you do:

\begin{semilogxaxis}[alph=0.5]

things are a bit different. The command that processes alph=0.5 doesn't belong to TikZ, rather it belongs to pgfplots. Thus, it works with keys in /pgfplots. In this case, the key /tikz/alph is executed, but apparently too late for the plot.3

Suggested fix

In order to fix the problem, simply define your alph key in a place that pgfplots considers when preparing the plot, like this:

\pgfkeys{/pgfplots/.cd,
    alph/.store in=\alphstore,
    alph=1
}

Actually, there is a shortcut for this, which is \pgfplotsset{alph/.store in=\alphstore, alph=1}. \pgfplotsset is to pgfplots what \tikzset is to TikZ, \tikzcdset to tikz-cd, \forestset to forest, \tcbset to tcolorbox, etc. Thanks to these \...set macros, you don't need to remember the prefix for each package by heart, but recall that there is more or less always a \...set macro that starts with the package name—for packages based on pgfkeys. This macro is usually quite useful for customizing things related to the considered package.

Your example with this change:

\documentclass{article}
\usepackage{pgfplots}

\begin{document}

\pgfplotsset{alph/.store in=\alphstore, alph=1}

\begin{tikzpicture}[declare function = { CFDfixedalph(\time) = \time^(\alphstore-1);}]
\begin{semilogxaxis}[alph=0.5]
\addplot[domain = 1e-6 : 1e6, samples = 100] {CFDfixedalph(x)};
\end{semilogxaxis}
\end{tikzpicture}

\end{document}

Screenshot

Other technique

Another way to do the same is to define /pgfplots/alph as a key that directly stores a value (as opposed to a key that stores code to be executed, which is what the .store in handler creates). This is maybe more in the pgfkeys spirit, but also significantly more verbose where you need to recover the value of the key (\pgfkeysvalueof{/pgfplots/alph}). That said, you can use a shortcut macro such as the \getalph macro in the following example to circumvent this verbosity problem, so this is probably a good solution too.

\documentclass{article}
\usepackage{pgfplots}

\begin{document}

\pgfplotsset{alph/.initial=1}
\newcommand*{\getalph}{\pgfkeysvalueof{/pgfplots/alph}} % convenient shortcut

\begin{tikzpicture}[
  declare function = { CFDfixedalph(\time) = \time^(\getalph-1); } ]
\begin{semilogxaxis}[alph=0.5]
\addplot[domain = 1e-6 : 1e6, samples = 100] {CFDfixedalph(x)};
\end{semilogxaxis}
\end{tikzpicture}

\end{document}

Footnotes

  1. A term used when talking about programming languages.

  2. cd stands for “change directory”. This is in analogy with filesystems; for instance, in many shells (POSIX, MS-DOS...), the cd command is used to change the current directory. /tikz/.cd tells pgfkeys to go to the /tikz “directory” (it is not a real filesystem directory; the whole pgfkeys directory hierarchy is only a tree-like structure held in memory). This new “current directory” (default path in pgfkeys terminology) will stay in effect until the next .cd (a nested call to \pgfkeys could also change it, but only inside the nested call). This causes subsequent relative paths to keys to be resolved using this path. For instance, \pgfkeys{/tikz/.cd, line width=2pt, line cap=round} is equivalent to \pgfkeys{/tikz/line width=2pt, /tikz/line cap=round}.

  3. This causes the following message to be printed:

    Package pgfplots Warning: Axis range for axis y is approximately empty; enlarging it (it is [1.0000000000:1.0000000000]) on input line 14.

  • Carefully and comprehensively explained. One final naive question if you don't mind: what is the meaning of .cd in both /tikz/.cd and /pgfplots/.cd? Additionally, is there a better and more brief way to define keys instead of what I did? Since I only copied and pasted this piece of code from old answer. – Diaa Aug 26 at 0:10
  • @frougon you should add a comment here: tex.stackexchange.com/a/235504/120578 – koleygr Aug 26 at 0:16
  • 1
    @Diaa The .cd is a pgfkeys handler, it is described under Handlers for Path Management in the TikZ & PGF manual (about p. 964). 〈key〉/.cd causes the default path to be set to 〈key〉 (default path which is reset to / at the beginning of each call to \pgfkeys). The default path is what is automatically prepended by \pgfkeys when you don't specify a full path for a key, as I explained in my answer. Yes, there is a slightly shorter way using \pgfplotsset, please see the latest edit. – frougon Aug 26 at 6:09
  • 1
    @koleygr Done, is that what you expected? – frougon Aug 26 at 6:35
  • @Diaa Maybe it's easier to understand this way: \pgfkeys{/tikz/.cd, foo=foovalue, bar=barvalue, baz} is equivalent to \pgfkeys{/tikz/foo=foovalue, /tikz/bar=barvalue, /tikz/baz}. While we're at it, it's very useful to understand that when you do \pgfkeys{/tikz/baz}, the /tikz/baz key is passed a value. This eventually results in /tikz/baz using its default value (not to be confused with the key's initial value; look for example at the tcolorbox manual: the distinction between default and initial values is made very clear for each key). – frougon Aug 26 at 6:57

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.