From 4dd393717b3ec1f67c90dcf5bc7a7e071aef8c2b Mon Sep 17 00:00:00 2001
From: Karl Berry <karl@freefriends.org>
Date: Fri, 5 Nov 2021 22:01:30 +0000
Subject: bodeplot (5nov21)

git-svn-id: svn://tug.org/texlive/trunk@60958 c570f23f-e606-0410-a88d-b1316a301751
---
 .../texmf-dist/source/latex/bodeplot/bodeplot.dtx  | 372 +++++++++++++--------
 1 file changed, 226 insertions(+), 146 deletions(-)

(limited to 'Master/texmf-dist/source/latex/bodeplot/bodeplot.dtx')

diff --git a/Master/texmf-dist/source/latex/bodeplot/bodeplot.dtx b/Master/texmf-dist/source/latex/bodeplot/bodeplot.dtx
index eff87445fd3..350e523ff60 100644
--- a/Master/texmf-dist/source/latex/bodeplot/bodeplot.dtx
+++ b/Master/texmf-dist/source/latex/bodeplot/bodeplot.dtx
@@ -27,7 +27,8 @@
 %
 %<*driver>
 \documentclass{ltxdoc}
-\usepackage{bodeplot,cprotect,hyperref}
+\usepackage{bodeplot,cprotect}
+\usepackage[colorlinks]{hyperref}
 \usetikzlibrary{decorations.markings,arrows.meta}
 \EnableCrossrefs
 \CodelineIndex
@@ -40,7 +41,7 @@
 %</driver>
 % \fi
 %
-% \CheckSum{1162}
+% \CheckSum{1287}
 %
 % \changes{v1.0}{2021/10/25}{Initial release}
 %
@@ -49,15 +50,15 @@
 % \DoNotIndex{\newcommand,\xdef,\gdef,\def,\edef,\addplot,\approx,\arabic,\opt,\typ,\obj,\else,\if@pgfarg,\fi,\begin,\end,\feature,\footnotesize,\draw,\detokenize,\DeclareOption,\foreach,\ifdim,\ifodd,\Im,\Re,\let,\newif,\nextgroupplot,\noexpand,\expandafter,\unexpanded,\PackageError,\PackageWarning,\relax,\RequirePackage,\tikzset,\pgfmathsetmacro,\pgfmathtruncatemacro,\ProcessOptions}
 %
 % \title{The \textsf{bodeplot} package\thanks{This document
-% corresponds to \textsf{bodeplot}~\fileversion,
-% dated \filedate.}}
+% corresponds to \textsf{bodeplot}~v1.0.3,
+% dated November 3, 2021.}}
 % \author{Rushikesh Kamalapurkar \\ \texttt{rlkamalapurkar@gmail.com}}
 %
 % \maketitle
 % \tableofcontents
 % \section{Introduction}
 %
-% Generate Bode, Nyquist, and Nichols plots for transfer functions in the canonical (TF) form \begin{equation}G(s) = e^{-Ts}\frac{b_ms^m+\cdots+b_1s+b_0}{a_ns^n+\cdots+a_1s+a_0}\label{eq:TF}\end{equation} and the zero-pole-gain (ZPK) form \begin{equation}G(s) = Ke^{-Ts}\frac{(s-z_1)(s-z_2)\cdots(s-z_m)}{(s-p_1)(s-p_2)\cdots(s-p_n)}.\label{eq:ZPK}\end{equation} In the equations above, $b_m,\cdots,b_0$ and $a_n,\cdots,a_0$ are real coefficients, $T\geq 0$ is the loop delay, $z_1,\cdots,z_m$ and $p_1,\cdots,p_n$ are complex zeros and poles of the transfer function, respectively, and $K\in \Re$ is the loop gain. For transfer functions in the ZPK format in (\ref{eq:ZPK}) with zero delay, this package also supports linear and asymptotic approximation of Bode plots.
+% Generate Bode, Nyquist, and Nichols plots for transfer functions in the canonical (TF) form \begin{equation}G(s) = e^{-Ts}\frac{b_ms^m+\cdots+b_1s+b_0}{a_ns^n+\cdots+a_1s+a_0}\label{eq:TF}\end{equation} and the zero-pole-gain (ZPK) form \begin{equation}G(s) = Ke^{-Ts}\frac{(s-z_1)(s-z_2)\cdots(s-z_m)}{(s-p_1)(s-p_2)\cdots(s-p_n)}.\label{eq:ZPK}\end{equation} In the equations above, $b_m,\cdots,b_0$ and $a_n,\cdots,a_0$ are real coefficients, $T\geq 0$ is the loop delay, $z_1,\cdots,z_m$ and $p_1,\cdots,p_n$ are complex zeros and poles of the transfer function, respectively, and $K\in \Re$ is the loop gain. For transfer functions in the ZPK format in (\ref{eq:ZPK}) with zero delay, this package also supports linear and asymptotic approximation of Bode plots. \textbf{Limitation:} in TF form, the phase angles are always between 0 and 360$^\circ$, As such, the Bode phase plots and the Nyquist and Nichols plots will have phase wrapping discontinuities. I do not know how this can be rectified, pull requests are welcome!
 %
 % \section{Usage}
 % \subsection{Bode plots}
@@ -81,6 +82,7 @@
 %  \item |plot/{opt}|: adds options |{opt}| to |\addplot| macros for both the magnitude and the phase plots.
 %  \item |axes/{opt}|: adds options |{opt}| to |\nextgroupplot| macros for both the magnitude and the phase plots.
 %  \item |group/{opt}|: adds options |{opt}| to the |groupplot| environment.
+%  \item |tikz/{opt}|: adds options |{opt}| to the |tikzpicture| environment.
 %  \item |approx/linear|: plots linear approximation.
 %  \item |approx/asymptotic|: plots asymptotic approximation.
 % \end{itemize}
@@ -114,7 +116,7 @@
 %
 % \begin{figure}
 % \begin{center}
-% \BodeZPK[plot/mag/{red,thick},plot/ph/{blue,thick},axes/mag/{ytick distance=40,xmajorticks=true,xlabel={Frequency (rad/s)}},axes/ph/{ytick distance=90},approx/linear,group/{group style={group size = 2 by 1,horizontal sep=2cm},width=4cm,height=2cm},] {z/{0,{-0.1,-0.5},{-0.1,0.5}},p/{{-0.5,-10},{-0.5,10}},g/10} {0.01} {100}
+% \BodeZPK[plot/mag/{red,thick},plot/ph/{blue,thick},axes/mag/{ytick distance=40,xmajorticks=true,xlabel={Frequency (rad/s)}},axes/ph/{ytick distance=90},approx/linear,group/{group style={group size = 2 by 1,horizontal sep=2cm},width=4cm,height=2cm}] {z/{0,{-0.1,-0.5},{-0.1,0.5}},p/{{-0.5,-10},{-0.5,10}},g/10} {0.01} {100}
 % \cprotect\caption{\label{customBode}Customization of the default |\BodeZPK| macro.}
 % \end{center}
 % \end{figure}
@@ -166,7 +168,7 @@
 %\end{BodePlot}
 %
 %\begin{BodePlot}[ylabel={Phase ($^{\circ}$)},
-%  height=2cm, width=4cm, ytick distance=90,] {0.01} {100}
+%  height=2cm, width=4cm, ytick distance=90] {0.01} {100}
 %  \addBodeZPKPlots[
 %    true/{black,thick},
 %    linear/{red,dashed,thick},
@@ -188,7 +190,7 @@
 %      {z/{0,{-0.1,-0.5},{-0.1,0.5}},p/{{-0.1,-10},{-0.1,10}},k/10}
 %    \end{BodePlot}
 %    \begin{BodePlot}[ylabel={Phase ($^{\circ}$)},
-%      height=2cm, width=4cm, ytick distance=90,] {0.01} {100}
+%      height=2cm, width=4cm, ytick distance=90] {0.01} {100}
 %
 %      \addBodeZPKPlots[
 %        true/{black,thick},
@@ -303,7 +305,7 @@
 % \hspace*{2em}\marg{z/\marg{zeros},p/\marg{poles},k/\marg{gain},d/\marg{delay}}\\
 % \hspace*{2em}\marg{min-freq}\marg{max-freq}
 %
-% \noindent Plots the Nyquist plot of a transfer function given in ZPK format with a thick red $+$ marking the critical point (-1,0). The mandatory arguments are the same as |\BodeZPK|. Since there is only one plot in a Nyquist diagram, the |\typ| specifier in the optional argument tuples is not needed. As such, the supported optional argument tuples are |plot/{opt}|, which passes |{opt}| to |\addplot| and |axes/{opt}|, which passes |{\opt}| to the |axis| environment. Asymptotic/linear approximations are not supported in Nyquist plots. If just |{opt}| is provided as the optional argument, it is interpreted as |plot/{opt}|. Arrows to indicate the direction of increasing $\omega$ can be added by adding |\usetikzlibrary{decorations.markings}| and |\usetikzlibrary{arrows.meta}| to the preamble and then passing a tuple of the form\\
+% \noindent Plots the Nyquist plot of a transfer function given in ZPK format with a thick red $+$ marking the critical point (-1,0). The mandatory arguments are the same as |\BodeZPK|. Since there is only one plot in a Nyquist diagram, the |\typ| specifier in the optional argument tuples is not needed. As such, the supported optional argument tuples are |plot/{opt}|, which passes |{opt}| to |\addplot|, |axes/{opt}|, which passes |{\opt}| to the |axis| environment, and |tikz/{opt}|, which passes |{\opt}| to the |tikzpicture| environment. Asymptotic/linear approximations are not supported in Nyquist plots. If just |{opt}| is provided as the optional argument, it is interpreted as |plot/{opt}|. Arrows to indicate the direction of increasing $\omega$ can be added by adding |\usetikzlibrary{decorations.markings}| and |\usetikzlibrary{arrows.meta}| to the preamble and then passing a tuple of the form\\
 %|plot/{postaction=decorate,decoration={markings,|\\
 %|  mark=between positions 0.1 and 0.9 step 5em with|\\
 %|  {\arrow{Stealth| |[length=2mm, blue]}}}}|\\
@@ -423,6 +425,7 @@
 % \begin{macro}{\n@pow}
 % \begin{macro}{idGnuplot}
 % \begin{macro}{gnuplot def}
+% \changes{v1.0.3}{2021/11/03}{Added jobname to gnuplot prefix}
 % \begin{macro}{gnuplot degrees}
 % This code is needed to support both |pgfplots| and |gnuplot| simultaneously. New macros are defined for the |pow| and |mod| functions to address differences between the two math engines. We start by processing the |pgf| class option.
 %    \begin{macrocode}
@@ -448,7 +451,7 @@
   \tikzset{%
     gnuplot def/.style={%
       id=\arabic{idGnuplot},
-      prefix=gnuplot/
+      prefix=gnuplot/\jobname
     }%
   }
 %    \end{macrocode}
@@ -753,97 +756,105 @@
   \gdef\func@ph{}%
   \build@ZPK@plot{\func@mag}{\func@ph}{\opt@approx}{#2}%
 %    \end{macrocode}
-% The |\noexpand| macros below are needed to so that only the macro |\opt@group| is expanded.
+% The |\noexpand| macros below are needed to so that only the macro |\opt@group| is expanded. \changes{v1.0.3}{2021/11/03}{Added Tikz option}
 %    \begin{macrocode}
-  \edef\temp@cmd{\noexpand\begin{tikzpicture}\noexpand\begin{groupplot}[%
-    bodeStyle,
-    xmin={#3},
-    xmax={#4},
-    domain=#3:#4,
-    height=2.5cm,
-    xmode=log,
-    group style = {group size = 1 by 2,vertical sep=0.25cm,},
-    \opt@group,]}
+  \edef\temp@cmd{\noexpand\begin{tikzpicture}[\opt@tikz]%
+    \noexpand\begin{groupplot}[%
+      bodeStyle,
+      xmin={#3},
+      xmax={#4},
+      domain=#3:#4,
+      height=2.5cm,
+      xmode=log,
+      group style = {group size = 1 by 2,vertical sep=0.25cm},
+      \opt@group
+    ]%
+  }%
   \temp@cmd
 %    \end{macrocode}
 % To ensure frequency tick marks on magnitude and the phase plots are always aligned, we use the |groupplot| library. The |\expandafter| chain below is used to expand macros in the plot and group optional arguments.
 %    \begin{macrocode}
-  \if@pgfarg
-    \expandafter\nextgroupplot\expandafter[ytick distance=20,
-      ylabel={Gain (dB)},xmajorticks=false,\optmag@axes]
-    \edef\temp@cmd{\noexpand\addplot[thick,\optmag@plot]}%
-    \temp@cmd {\func@mag};
-    \optmag@commands;
-    \expandafter\nextgroupplot\expandafter[ytick distance=45,
-      ylabel={Phase ($^{\circ}$)},xlabel={Frequency (rad/s)},\optph@axes]
-    \edef\temp@cmd{\noexpand\addplot[thick,\optph@plot]}%
-    \temp@cmd {\func@ph};
-    \optph@commands;
-  \else
+      \if@pgfarg
+        \expandafter\nextgroupplot\expandafter[ytick distance=20,
+          ylabel={Gain (dB)},xmajorticks=false,\optmag@axes]
+        \edef\temp@cmd{\noexpand\addplot[thick,\optmag@plot]}%
+        \temp@cmd {\func@mag};
+        \optmag@commands;
+        \expandafter\nextgroupplot\expandafter[ytick distance=45,
+          ylabel={Phase ($^{\circ}$)},xlabel={Frequency (rad/s)},\optph@axes]
+        \edef\temp@cmd{\noexpand\addplot[thick,\optph@plot]}%
+        \temp@cmd {\func@ph};
+        \optph@commands;
+      \else
 %    \end{macrocode}
 % In |gnuplot| mode, we increment the |idGnuplot| counter before every plot to make sure that new and reusable |.gnuplot| and |.table| files are generated for every plot.
 %    \begin{macrocode}
-    \stepcounter{idGnuplot}
-    \expandafter\nextgroupplot\expandafter[ytick distance=20,
-      ylabel={Gain (dB)},xmajorticks=false,\optmag@axes]
-    \edef\temp@cmd{\noexpand\addplot[thick,\optmag@plot]}%
-    \temp@cmd gnuplot[gnuplot degrees,gnuplot def] {\func@mag};
-    \optmag@commands;
-    \stepcounter{idGnuplot}
-    \expandafter\nextgroupplot\expandafter[ytick distance=45,
-      ylabel={Phase ($^{\circ}$)},xlabel={Frequency (rad/s)},\optph@axes]
-    \edef\temp@cmd{\noexpand\addplot[thick,\optph@plot]}%
-    \temp@cmd gnuplot[gnuplot degrees,gnuplot def] {\func@ph};
-    \optph@commands;
-  \fi
-  \end{groupplot}\end{tikzpicture}
+      \stepcounter{idGnuplot}
+      \expandafter\nextgroupplot\expandafter[ytick distance=20,
+        ylabel={Gain (dB)},xmajorticks=false,\optmag@axes]
+      \edef\temp@cmd{\noexpand\addplot[thick,\optmag@plot]}%
+      \temp@cmd gnuplot[gnuplot degrees,gnuplot def] {\func@mag};
+      \optmag@commands;
+      \stepcounter{idGnuplot}
+      \expandafter\nextgroupplot\expandafter[ytick distance=45,
+        ylabel={Phase ($^{\circ}$)},xlabel={Frequency (rad/s)},\optph@axes]
+      \edef\temp@cmd{\noexpand\addplot[thick,\optph@plot]}%
+      \temp@cmd gnuplot[gnuplot degrees,gnuplot def] {\func@ph};
+      \optph@commands;
+    \fi
+    \end{groupplot}
+  \end{tikzpicture}
 }
 %    \end{macrocode}
 % \end{macro}
 % \begin{macro}{\BodeTF}
-% Implementation of this macro is very similar to the |\BodeZPK| macro above. The only difference is the lack of linear and asymptotic plots and slightly different parsing of the mandatory arguments.
+% Implementation of this macro is very similar to the |\BodeZPK| macro above. The only difference is the lack of linear and asymptotic plots and slightly different parsing of the mandatory arguments. \changes{v1.0.3}{2021/11/03}{Added Tikz option}
 %    \begin{macrocode}
 \newcommand{\BodeTF}[4][]{%
   \parse@opt{#1}%
   \gdef\func@mag{}%
   \gdef\func@ph{}%
   \build@TF@plot{\func@mag}{\func@ph}{#2}%
-  \edef\temp@cmd{\noexpand\begin{tikzpicture}\noexpand\begin{groupplot}[%
-    bodeStyle,
-    xmin={#3},
-    xmax={#4},
-    domain=#3:#4,
-    height=2.5cm,
-    xmode=log,
-    group style = {group size = 1 by 2,vertical sep=0.25cm,},
-    \opt@group,]}
+  \edef\temp@cmd{\noexpand\begin{tikzpicture}[\opt@tikz]%
+    \noexpand\begin{groupplot}[%
+      bodeStyle,
+      xmin={#3},
+      xmax={#4},
+      domain=#3:#4,
+      height=2.5cm,
+      xmode=log,
+      group style = {group size = 1 by 2,vertical sep=0.25cm},
+      \opt@group
+    ]%
+  }%
   \temp@cmd
-  \if@pgfarg
-    \expandafter\nextgroupplot\expandafter[ytick distance=20,
-      ylabel={Gain (dB)},xmajorticks=false,\optmag@axes]
-    \edef\temp@cmd{\noexpand\addplot[thick,\optmag@plot]}%
-    \temp@cmd {\func@mag};
-    \optmag@commands;%
-    \expandafter\nextgroupplot\expandafter[ytick distance=45,
-      ylabel={Phase ($^{\circ}$)},xlabel={Frequency (rad/s)},\optph@axes]
-    \edef\temp@cmd{\noexpand\addplot[thick,\optph@plot]}%
-    \temp@cmd {\func@ph};
-    \optph@commands;%
-  \else
-    \stepcounter{idGnuplot}%
-    \expandafter\nextgroupplot\expandafter[ytick distance=20,
-      ylabel={Gain (dB)},xmajorticks=false,\optmag@axes]
-    \edef\temp@cmd{\noexpand\addplot[thick,\optmag@plot]}%
-    \temp@cmd gnuplot[gnuplot degrees,gnuplot def] {\func@mag};
-    \optmag@commands;%
-    \stepcounter{idGnuplot}%
-    \expandafter\nextgroupplot\expandafter[ytick distance=45,
-      ylabel={Phase ($^{\circ}$)},xlabel={Frequency (rad/s)},\optph@axes]
-    \edef\temp@cmd{\noexpand\addplot[thick,\optph@plot]}%
-    \temp@cmd gnuplot[gnuplot degrees,gnuplot def] {\func@ph};
-    \optph@commands;%
-  \fi
-  \end{groupplot}\end{tikzpicture}
+      \if@pgfarg
+        \expandafter\nextgroupplot\expandafter[ytick distance=20,
+          ylabel={Gain (dB)},xmajorticks=false,\optmag@axes]
+        \edef\temp@cmd{\noexpand\addplot[thick,\optmag@plot]}%
+        \temp@cmd {\func@mag};
+        \optmag@commands;
+        \expandafter\nextgroupplot\expandafter[ytick distance=45,
+          ylabel={Phase ($^{\circ}$)},xlabel={Frequency (rad/s)},\optph@axes]
+        \edef\temp@cmd{\noexpand\addplot[thick,\optph@plot]}%
+        \temp@cmd {\func@ph};
+        \optph@commands;
+      \else
+        \stepcounter{idGnuplot}%
+        \expandafter\nextgroupplot\expandafter[ytick distance=20,
+          ylabel={Gain (dB)},xmajorticks=false,\optmag@axes]
+        \edef\temp@cmd{\noexpand\addplot[thick,\optmag@plot]}%
+        \temp@cmd gnuplot[gnuplot degrees,gnuplot def] {\func@mag};
+        \optmag@commands;
+        \stepcounter{idGnuplot}%
+        \expandafter\nextgroupplot\expandafter[ytick distance=45,
+          ylabel={Phase ($^{\circ}$)},xlabel={Frequency (rad/s)},\optph@axes]
+        \edef\temp@cmd{\noexpand\addplot[thick,\optph@plot]}%
+        \temp@cmd gnuplot[gnuplot degrees,gnuplot def] {\func@ph};
+        \optph@commands;
+      \fi
+    \end{groupplot}
+  \end{tikzpicture}
 }
 %    \end{macrocode} 
 % \end{macro}
@@ -905,20 +916,24 @@
 %    \end{macrocode}
 %\end{macro}
 % \begin{environment}{BodePlot}
-% An environment to host macros that pass parametric functions to |\addplot| macros. Uses the defaults specified in |bodeStyle| to create a shortcut that includes the |tikzpicture| and |semilogaxis| environments.
+% An environment to host macros that pass parametric functions to |\addplot| macros. Uses the defaults specified in |bodeStyle| to create a shortcut that includes the |tikzpicture| and |semilogaxis| environments. \changes{v1.0.3}{2021/11/03}{Added tikz option to environments}
 %    \begin{macrocode}
 \newenvironment{BodePlot}[3][]{%
-  \begin{tikzpicture}
-    \begin{semilogxaxis}[%
+  \parse@env@opt{#1}%
+  \edef\temp@cmd{\noexpand\begin{tikzpicture}[\opt@tikz]
+    \noexpand\begin{semilogxaxis}[%
       bodeStyle,
       xmin={#2},
       xmax={#3},
       domain=#2:#3,
       height=2.5cm,
       xlabel={Frequency (rad/s)},
-      #1]
+      \opt@axes
+    ]%
+  }%
+  \temp@cmd
 }{
-  \end{semilogxaxis}
+    \end{semilogxaxis}
   \end{tikzpicture}
 }
 %    \end{macrocode}
@@ -1075,7 +1090,7 @@
 %    \end{macrocode}
 %\end{macro}
 % \begin{macro}{\parse@opt}
-% Parses options supplied to the main Bode macros. A |for| loop over tuples of the form |\obj/\typ/\opt| with a long list of nested if-else statements does the job. The input |\obj| is either |plot|, |axes|, |group| or |approx|, and the corresponding |\opt| are passed to the |\addplot| macro, the |\nextgroupplot| macro, the |groupplot| environment, and the |\build@ZPK@plot| macros, respectively. The input tuples should not contain any macros that need to be passed to respective |pgf| macros unexpanded. If an input tuple needs to contain such a macro, the |\xdef| macros below need to be defined using |\unexpanded\expandafter{\opt}| instead of just |\opt|. For example, the |\parse@N@opt| macro in Section \ref{sec:NInternal} can pass macros in its arguments, unexpanded, to |pgf| plot macros and environments, which is useful, for example, when the user wishes to add direction arrows to Nyquist plots. I did not think such a use case would be encountered when plotting Bode plots.
+% Parses options supplied to the main Bode macros. A |for| loop over tuples of the form |\obj/\typ/\opt| with a long list of nested if-else statements does the job. If the input |\obj| is |plot|, |axes|, |group|, |approx|, or |tikz| the corresponding |\opt| are passed, unexpanded, to the |\addplot| macro, the |\nextgroupplot| macro, the |groupplot| environment, the |\build@ZPK@plot| macro, and the |tikzpicture| environment, respectively. If |\obj| is |commands|, the corresponding |\opt| are stored, unexpanded, in the macros |\optph@commands| and |\optmag@commands|, to be executed in appropriate |axis| environments. \changes{v1.0.3}{2021/11/03}{Added Tikz option}
 %    \begin{macrocode}
 \newcommand{\parse@opt}[1]{%
   \gdef\optmag@axes{}%
@@ -1084,38 +1099,39 @@
   \gdef\optmag@plot{}%
   \gdef\opt@group{}%
   \gdef\opt@approx{}%
-  \xdef\optph@commands{}%
-  \xdef\optmag@commands{}%
+  \gdef\optph@commands{}%
+  \gdef\optmag@commands{}%
+  \gdef\opt@tikz{}%
   \foreach \obj/\typ/\opt in {#1} {%
     \ifnum\pdfstrcmp{\obj}{plot}=0
       \ifnum\pdfstrcmp{\typ}{mag}=0
-        \xdef\optmag@plot{\optmag@plot,\opt}%
+        \xdef\optmag@plot{\unexpanded\expandafter{\opt}}%
       \else
         \ifnum\pdfstrcmp{\typ}{ph}=0
-          \xdef\optph@plot{\optph@plot,\opt}%
+          \xdef\optph@plot{\unexpanded\expandafter{\opt}}%
         \else
-          \xdef\optmag@plot{\optmag@plot,\opt}%
-          \xdef\optph@plot{\optph@plot,\opt}%
+          \xdef\optmag@plot{\unexpanded\expandafter{\opt}}%
+          \xdef\optph@plot{\unexpanded\expandafter{\opt}}%
         \fi
       \fi
     \else
       \ifnum\pdfstrcmp{\obj}{axes}=0
         \ifnum\pdfstrcmp{\typ}{mag}=0
-          \xdef\optmag@axes{\optmag@axes,\opt}%
+          \xdef\optmag@axes{\unexpanded\expandafter{\opt}}%
         \else
           \ifnum\pdfstrcmp{\typ}{ph}=0
-            \xdef\optph@axes{\optph@axes,\opt}%
+            \xdef\optph@axes{\unexpanded\expandafter{\opt}}%
           \else
-            \xdef\optmag@axes{\optmag@axes,\opt}%
-            \xdef\optph@axes{\optph@axes,\opt}%
+            \xdef\optmag@axes{\unexpanded\expandafter{\opt}}%
+            \xdef\optph@axes{\unexpanded\expandafter{\opt}}%
           \fi
         \fi
       \else
         \ifnum\pdfstrcmp{\obj}{group}=0
-          \xdef\opt@group{\opt@group,\opt}%
+          \xdef\opt@group{\unexpanded\expandafter{\opt}}%
         \else
           \ifnum\pdfstrcmp{\obj}{approx}=0
-            \xdef\opt@approx{\opt}%
+            \xdef\opt@approx{\unexpanded\expandafter{\opt}}%
           \else
             \ifnum\pdfstrcmp{\obj}{commands}=0
               \ifnum\pdfstrcmp{\typ}{phase}=0
@@ -1124,8 +1140,12 @@
                 \xdef\optmag@commands{\unexpanded\expandafter{\opt}}%
               \fi
             \else
-              \xdef\optmag@plot{\optmag@plot,\obj}%
-              \xdef\optph@plot{\optph@plot,\obj}%
+              \ifnum\pdfstrcmp{\obj}{tikz}=0
+                \xdef\opt@tikz{\unexpanded\expandafter{\opt}}%
+              \else
+                \xdef\optmag@plot{\optmag@plot,\unexpanded\expandafter{\obj}}%
+                \xdef\optph@plot{\optph@plot,\unexpanded\expandafter{\obj}}%
+              \fi
             \fi
           \fi
         \fi
@@ -1135,35 +1155,60 @@
 }
 %    \end{macrocode}
 %\end{macro}
+% \begin{macro}{\parse@env@opt}
+% Parses options supplied to the Bode, Nyquist, and Nichols environments. A |for| loop over tuples of the form |\obj/\opt|, processed using nested if-else statements does the job. The input |\obj| should either be |axes| or |tikz|, and the corresponding |\opt| are passed, unexpanded, to the |axis| environment and the |tikzpicture| environment, respectively. \changes{v1.0.3}{2021/11/03}{Added tikz option to environments}
+%    \begin{macrocode}
+\newcommand{\parse@env@opt}[1]{%
+  \gdef\opt@axes{}%
+  \gdef\opt@tikz{}%
+  \foreach \obj/\opt in {#1} {%
+    \ifnum\pdfstrcmp{\obj}{axes}=0
+      \xdef\opt@axes{\unexpanded\expandafter{\opt}}%
+    \else
+      \ifnum\pdfstrcmp{\obj}{tikz}=0
+        \xdef\opt@tikz{\unexpanded\expandafter{\opt}}%
+      \else
+        \xdef\opt@axes{\opt@axes,\unexpanded\expandafter{\obj}}%
+      \fi
+    \fi
+  }%
+}
+%    \end{macrocode}
+% \end{macro}
 % \subsection{Nyquist plots}
 % \subsubsection{User macros}
 % \begin{macro}{\NyquistZPK}
-% Converts magnitude and phase parametric functions built using |\build@ZPK@plot| into real part and imaginary part parametric functions. A plot of these is the Nyquist plot. The parametric functions are then plotted in a |tikzpicture| environment using the |\addplot| macro. Unless the package is loaded with the option |pgf|, the parametric functions are evaluated using |gnuplot|. A large number of samples is typically needed to get a smooth plot because frequencies near 0 result in plot points that are very close to each other. Linear frequency sampling is unnecessarily fine near zero and very coarse for large $\omega$. Logarithmic sampling makes it worse, perhaps inverse logarithmic sampling will help, merge requests are welcome!
+% Converts magnitude and phase parametric functions built using |\build@ZPK@plot| into real part and imaginary part parametric functions. A plot of these is the Nyquist plot. The parametric functions are then plotted in a |tikzpicture| environment using the |\addplot| macro. Unless the package is loaded with the option |pgf|, the parametric functions are evaluated using |gnuplot|. A large number of samples is typically needed to get a smooth plot because frequencies near 0 result in plot points that are very close to each other. Linear frequency sampling is unnecessarily fine near zero and very coarse for large $\omega$. Logarithmic sampling makes it worse, perhaps inverse logarithmic sampling will help, pull requests to fix that are welcome! \changes{v1.0.3}{2021/11/03}{Added commands and tikz options}
 %    \begin{macrocode}
 \newcommand{\NyquistZPK}[4][]{%
   \parse@N@opt{#1}%
   \gdef\func@mag{}%
   \gdef\func@ph{}%
   \build@ZPK@plot{\func@mag}{\func@ph}{}{#2}%
-  \edef\temp@cmd{\noexpand\begin{tikzpicture}\noexpand\begin{axis}[%
-        bodeStyle,
-        domain=#3:#4,
-        height=5cm,
-        xlabel={$\Re$},
-        ylabel={$\Im$},
-        samples=500,
-        \opt@axes,]}%
+  \edef\temp@cmd{\noexpand\begin{tikzpicture}[\opt@tikz]%
+    \noexpand\begin{axis}[%
+      bodeStyle,
+      domain=#3:#4,
+      height=5cm,
+      xlabel={$\Re$},
+      ylabel={$\Im$},
+      samples=500,
+      \opt@axes
+    ]%
+  }%
   \temp@cmd
       \addplot [only marks,mark=+,thick,red] (-1 , 0);
       \edef\temp@cmd{\noexpand\addplot[thick,\unexpanded\expandafter{\opt@plot}]}%
       \if@pgfarg
         \temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos(\func@ph)},
           {\n@pow{10}{((\func@mag)/20)}*sin(\func@ph)} );
+        \opt@commands;
       \else
         \stepcounter{idGnuplot}%
         \temp@cmd gnuplot[parametric,gnuplot degrees,gnuplot def] {%
           \n@pow{10}{((\func@mag)/20)}*cos(\func@ph),
           \n@pow{10}{((\func@mag)/20)}*sin(\func@ph)};
+        \opt@commands;
       \fi
     \end{axis}
   \end{tikzpicture}
@@ -1171,32 +1216,37 @@
 %    \end{macrocode}
 % \end{macro}
 % \begin{macro}{\NyquistTF}
-% Implementation of this macro is very similar to the |\NyquistZPK| macro above. The only difference is a slightly different parsing of the mandatory arguments via |\build@TF@plot|.
+% Implementation of this macro is very similar to the |\NyquistZPK| macro above. The only difference is a slightly different parsing of the mandatory arguments via |\build@TF@plot|. \changes{v1.0.3}{2021/11/03}{Added commands and tikz options}
 %    \begin{macrocode}
 \newcommand{\NyquistTF}[4][]{%
   \parse@N@opt{#1}%
   \gdef\func@mag{}%
   \gdef\func@ph{}%
   \build@TF@plot{\func@mag}{\func@ph}{#2}%
-  \edef\temp@cmd{\noexpand\begin{tikzpicture}\noexpand\begin{axis}[%
-        bodeStyle,
-        domain=#3:#4,
-        height=5cm,
-        xlabel={$\Re$},
-        ylabel={$\Im$},
-        samples=500,
-        \opt@axes,]}
+  \edef\temp@cmd{\noexpand\begin{tikzpicture}[\opt@tikz]%
+    \noexpand\begin{axis}[%
+      bodeStyle,
+      domain=#3:#4,
+      height=5cm,
+      xlabel={$\Re$},
+      ylabel={$\Im$},
+      samples=500,
+      \opt@axes
+    ]%
+  }%
   \temp@cmd
       \addplot [only marks,mark=+,thick,red] (-1 , 0);
       \edef\temp@cmd{\noexpand\addplot[thick,\unexpanded\expandafter{\opt@plot}]}%
       \if@pgfarg
         \temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos(\func@ph)},
           {\n@pow{10}{((\func@mag)/20)}*sin(\func@ph)} );
+        \opt@commands;
       \else
         \stepcounter{idGnuplot}%
         \temp@cmd gnuplot[parametric,gnuplot degrees,gnuplot def]{%
           \n@pow{10}{((\func@mag)/20)}*cos(\func@ph),
           \n@pow{10}{((\func@mag)/20)}*sin(\func@ph)};
+        \opt@commands;
       \fi
     \end{axis}
   \end{tikzpicture}
@@ -1242,17 +1292,21 @@
 %    \end{macrocode}
 %\end{macro}
 %\begin{macro}{NyquistPlot}
-% An environment to host |\addNyquist...| macros that pass parametric functions to |\addplot|. Uses the defaults specified in |bodeStyle| to create a shortcut that includes the |tikzpicture| and |axis| environments.
+% An environment to host |\addNyquist...| macros that pass parametric functions to |\addplot|. Uses the defaults specified in |bodeStyle| to create a shortcut that includes the |tikzpicture| and |axis| environments. \changes{v1.0.3}{2021/11/03}{Added tikz option to environments}
 %    \begin{macrocode}
 \newenvironment{NyquistPlot}[3][]{%
-  \begin{tikzpicture}
-    \begin{axis}[%
+\parse@env@opt{#1}%
+  \edef\temp@cmd{\noexpand\begin{tikzpicture}[\opt@tikz]%
+    \noexpand\begin{axis}[%
       bodeStyle,
       height=5cm,
       domain=#2:#3,
       xlabel={$\Re$},
       ylabel={$\Im$},
-      #1]
+      \opt@axes
+    ]%
+  }%
+  \temp@cmd
     \addplot [only marks,mark=+,thick,red] (-1 , 0);
 }{%
     \end{axis}
@@ -1261,12 +1315,14 @@
 %    \end{macrocode}
 %\end{macro}
 % \subsubsection{Internal commands\label{sec:NInternal}}
-% \begin{macro}{\parse@opt}
-% Parses options supplied to the main Nyquist and Nichols macros. A |for| loop over tuples of the form |\obj/\opt|, processed using nested if-else statements does the job. The input |\obj| is either |plot| or |axes|, and the corresponding |\opt| are passed to the |\addplot| macro and the |axis| environment, respectively. If the input tuples contain macros, they are to be passed to respective |pgf| macros unexpanded.
+% \begin{macro}{\parse@N@opt}
+% Parses options supplied to the main Nyquist and Nichols macros. A |for| loop over tuples of the form |\obj/\opt|, processed using nested if-else statements does the job. If the input |\obj| is |plot|, |axes|, or |tikz| then the corresponding |\opt| are passed, unexpanded, to the |\addplot| macro, the |axis| environment, and the |tikzpicture| environment, respectively. \changes{v1.0.3}{2021/11/03}{Added commands and tikz options}
 %    \begin{macrocode}
 \newcommand{\parse@N@opt}[1]{%
   \gdef\opt@axes{}%
   \gdef\opt@plot{}%
+  \gdef\opt@commands{}%
+  \gdef\opt@tikz{}
   \foreach \obj/\opt in {#1} {%
     \ifnum\pdfstrcmp{\obj}{axes}=0
       \xdef\opt@axes{\unexpanded\expandafter{\opt}}%
@@ -1274,7 +1330,15 @@
       \ifnum\pdfstrcmp{\obj}{plot}=0
         \xdef\opt@plot{\unexpanded\expandafter{\opt}}%
       \else
-        \xdef\opt@plot{\unexpanded\expandafter{\obj}}%
+        \ifnum\pdfstrcmp{\obj}{commands}=0
+          \xdef\opt@commands{\unexpanded\expandafter{\opt}}%
+        \else
+          \ifnum\pdfstrcmp{\obj}{tikz}=0
+            \xdef\opt@tikz{\unexpanded\expandafter{\opt}}%
+          \else
+            \xdef\opt@plot{\opt@plot,\unexpanded\expandafter{\obj}}%
+          \fi
+        \fi
       \fi
     \fi
   }%
@@ -1283,8 +1347,11 @@
 % \end{macro}
 % \subsection{Nichols charts}
 % \begin{macro}{\NicholsZPK}
+% \changes{v1.0.3}{2021/11/03}{Added commands and tikz options}
 % \begin{macro}{\NicholsTF}
+% \changes{v1.0.3}{2021/11/03}{Added commands and tikz options}
 % \begin{macro}{NicholsChart}
+% \changes{v1.0.3}{2021/11/03}{Added tikz option to environments}
 % \begin{macro}{\addNicholsZPKChart}
 % \begin{macro}{\addNicholsTFChart}
 % These macros and the |NicholsChart| environment generate Nichols charts, and they are implemented similar to their Nyquist counterparts.
@@ -1294,22 +1361,27 @@
   \gdef\func@mag{}%
   \gdef\func@ph{}%
   \build@ZPK@plot{\func@mag}{\func@ph}{}{#2}%
-  \edef\temp@cmd{\noexpand\begin{tikzpicture}\noexpand\begin{axis}[%
-        bodeStyle,
-        domain=#3:#4,
-        height=5cm,
-        xlabel={Phase (degrees)},
-        ylabel={Gain (dB)},
-        samples=500,
-        \opt@axes]}
+  \edef\temp@cmd{\noexpand\begin{tikzpicture}[\opt@tikz]%
+    \noexpand\begin{axis}[%
+      bodeStyle,
+      domain=#3:#4,
+      height=5cm,
+      xlabel={Phase (degrees)},
+      ylabel={Gain (dB)},
+      samples=500,
+      \opt@axes
+    ]%
+  }%
   \temp@cmd
       \edef\temp@cmd{\noexpand\addplot[thick,\opt@plot]}%
       \if@pgfarg
         \temp@cmd ( {\func@ph} , {\func@mag} );
+        \opt@commands;
       \else
         \stepcounter{idGnuplot}%
         \temp@cmd gnuplot[parametric, gnuplot degrees, gnuplot def]
           { \func@ph , \func@mag };
+        \opt@commands;
       \fi
     \end{axis}
   \end{tikzpicture}
@@ -1319,29 +1391,34 @@
   \gdef\func@mag{}%
   \gdef\func@ph{}%
   \build@TF@plot{\func@mag}{\func@ph}{#2}%
-  \edef\temp@cmd{\noexpand\begin{tikzpicture}\noexpand\begin{axis}[%
-        bodeStyle,
-        domain=#3:#4,
-        height=5cm,
-        xlabel={Phase (degrees)},
-        ylabel={Gain (dB)},
-        samples=500,
-        \opt@axes]}
+  \edef\temp@cmd{\noexpand\begin{tikzpicture}[\opt@tikz]%
+    \noexpand\begin{axis}[%
+      bodeStyle,
+      domain=#3:#4,
+      height=5cm,
+      xlabel={Phase (degrees)},
+      ylabel={Gain (dB)},
+      samples=500,
+      \opt@axes
+    ]%
+  }%
   \temp@cmd
       \edef\temp@cmd{\noexpand\addplot[thick,\opt@plot]}%
       \if@pgfarg
         \temp@cmd ( {\func@ph} , {\func@mag} );
+        \opt@commands;
       \else
         \stepcounter{idGnuplot}%
         \temp@cmd gnuplot[parametric, gnuplot degrees, gnuplot def]
           { \func@ph , \func@mag };
+        \opt@commands;
       \fi
     \end{axis}
   \end{tikzpicture}
 }
 \newenvironment{NicholsChart}[3][]{%
-  \begin{tikzpicture}
-    \begin{axis}[%
+  \edef\temp@cmd{\noexpand\begin{tikzpicture}[\opt@tikz]%
+    \noexpand\begin{axis}[%
       bodeStyle,
       domain=#2:#3,
       height=5cm,
@@ -1349,7 +1426,10 @@
       xtick distance=15,
       xlabel={Phase (degrees)},
       ylabel={Gain (dB)},
-      #1]
+      \opt@axes
+    ]%
+  }%
+  \temp@cmd
 }{
     \end{axis}
   \end{tikzpicture}
-- 
cgit v1.2.3

