summaryrefslogtreecommitdiff
path: root/graphics
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2024-04-19 03:00:56 +0000
committerNorbert Preining <norbert@preining.info>2024-04-19 03:00:56 +0000
commit059925fc0cab13a83a74089aeee51f4b09bbd914 (patch)
tree4130d56b2ad50f7cdf9dc3ef256f7848218087de /graphics
parent01aeff9f14b706b8b64c4f782f2253e431e89e49 (diff)
CTAN sync 202404190300
Diffstat (limited to 'graphics')
-rw-r--r--graphics/pgf/contrib/bodeplot/README.md5
-rw-r--r--graphics/pgf/contrib/bodeplot/bodeplot-2024-02-06.sty1112
-rw-r--r--graphics/pgf/contrib/bodeplot/bodeplot.dtx46
-rw-r--r--graphics/pgf/contrib/bodeplot/bodeplot.ins4
-rw-r--r--graphics/pgf/contrib/bodeplot/bodeplot.pdfbin1099158 -> 1099922 bytes
5 files changed, 1141 insertions, 26 deletions
diff --git a/graphics/pgf/contrib/bodeplot/README.md b/graphics/pgf/contrib/bodeplot/README.md
index ba00b9e9ee..037319a23a 100644
--- a/graphics/pgf/contrib/bodeplot/README.md
+++ b/graphics/pgf/contrib/bodeplot/README.md
@@ -7,8 +7,9 @@ Author: Rushikesh Kamalapurkar ([rlkamalapurkar@gmail.com](mailto:rlkamalapurkar
License: [LPPL-1.3c](https://github.com/rlkamalapurkar/bodeplot/blob/main/LICENSE)
## Limitations
- 1. TF commands are wrapped between -180 and 180 degrees in `pgf` mode.
- 2. Version 1.0.8 and newer store `gnuplot` temporary files in the working directory. Use class option `declutter` to restore pre-v1.0.8 behavior. Option `declutter` can cause errors if used with a `tikzexternalize` prefix.
+ 1 Before version 1.2, in `pgf` mode, the package set `trig format plots` to `rad` globally. Version 1.2 onwards, this option is passed to each `addplot` command individually so it does not affect non-`bodeplot` plots. To roll back to pre-v1.2 behavior, load the package with `\usepackage[pgf]{bodeplot}[=2024-02-06]`.
+ 2. TF commands are wrapped between -180 and 180 degrees in `pgf` mode.
+ 3. Version 1.0.8 and newer store `gnuplot` temporary files in the working directory. Use class option `declutter` to restore pre-v1.0.8 behavior. Option `declutter` can cause errors if used with a `tikzexternalize` prefix.
## Compilation instructions
1) `latex bodeplot.ins` to generate `bodeplot.sty`
diff --git a/graphics/pgf/contrib/bodeplot/bodeplot-2024-02-06.sty b/graphics/pgf/contrib/bodeplot/bodeplot-2024-02-06.sty
new file mode 100644
index 0000000000..df2f610361
--- /dev/null
+++ b/graphics/pgf/contrib/bodeplot/bodeplot-2024-02-06.sty
@@ -0,0 +1,1112 @@
+%%
+%% This is file `bodeplot.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% bodeplot.dtx (with options: `package')
+%% This is a generated file.
+%% Copyright (C) 2021 by Rushikesh Kamalapurkar
+%% This file may be distributed and/or modified under the
+%% conditions of the LaTeX Project Public License, either
+%% version 1.3c of this license or (at your option) any later
+%% version. The latest version of this license is in:
+%% http://www.latex-project.org/lppl.txt
+%% and version 1.3c or later is part of all distributions of
+%% LaTeX version 2006/05/20 or later.
+\NeedsTeXFormat{LaTeX2e}[2006/05/20]
+\ProvidesPackage{bodeplot}
+\RequirePackage{pdftexcmds}
+\RequirePackage{ifplatform}
+\RequirePackage{xparse}
+\RequirePackage{pgfplots}
+ \pgfplotsset{compat=1.18}
+ \usepgfplotslibrary{groupplots}
+
+\newif\if@pgfarg\@pgfargfalse
+\DeclareOption{pgf}{
+ \@pgfargtrue
+}
+\newif\if@declutterarg\@declutterargfalse
+\DeclareOption{declutter}{
+ \@declutterargtrue
+}
+\newif\if@radarg\@radargfalse
+\DeclareOption{rad}{
+ \@radargtrue
+}
+\newif\if@hzarg\@hzargfalse
+\DeclareOption{Hz}{
+ \@hzargtrue
+}
+\ProcessOptions\relax
+\newcommand{\n@mod}[2]{(#1)-((round((#1)/(#2)))*(#2))}
+\newcommand{\n@mod@p}[2]{(#1)-((floor((#1)/(#2)))*(#2))}
+\newcommand{\n@mod@n}[2]{(#1)-((floor((#1)/(#2))+1)*(#2))}
+\if@pgfarg
+ \newcommand{\n@pow}[2]{(#1)^(#2)}
+ \pgfplotsset{
+ trig format plots=rad
+ }
+\else
+ \newcommand{\n@pow}[2]{(#1)**(#2)}
+ \newcounter{gnuplot@id}
+ \setcounter{gnuplot@id}{0}
+ \if@declutterarg
+ \edef\bodeplot@prefix{gnuplot/\jobname}
+ \else
+ \edef\bodeplot@prefix{\jobname}
+ \fi
+ \tikzset{
+ gnuplot@prefix/.style={
+ id=\arabic{gnuplot@id},
+ prefix=\bodeplot@prefix
+ }
+ }
+ \ifwindows\else
+ \if@declutterarg
+ \immediate\write18{mkdir -p gnuplot}
+ \fi
+ \fi
+\fi
+\newif\if@babel\@babelfalse
+\AtBeginDocument{%
+ \@ifpackageloaded{babel}{%
+ \@babeltrue
+ \let\shorthand@list\@empty
+ \def\do#1{%
+ \begingroup
+ \lccode`\~=`#1\relax
+ \lowercase{\ifbabelshorthand~{\g@addto@macro\shorthand@list{~}}{}}
+ \endgroup
+ }
+ \dospecials
+ }{}
+}
+\pgfplotsset{
+ bode@style/.style = {
+ label style={font=\footnotesize},
+ tick label style={font=\footnotesize},
+ grid=both,
+ major grid style={color=gray!80},
+ minor grid style={color=gray!20},
+ x label style={at={(ticklabel cs:0.5)},anchor=near ticklabel},
+ y label style={at={(ticklabel cs:0.5)},anchor=near ticklabel},
+ scale only axis,
+ samples=200,
+ width=5cm,
+ log basis x=10
+ }
+}
+\pgfplotsset{freq@filter/.style = {}}
+\def\freq@scale{1}
+\pgfplotsset{freq@label/.style = {xlabel = {Frequency (rad/s)}}}
+\pgfplotsset{ph@x@label/.style = {xlabel={Phase (deg)}}}
+\pgfplotsset{ph@y@label/.style = {ylabel={Phase (deg)}}}
+\def\ph@scale{180/pi}
+\if@radarg
+ \pgfplotsset{ph@y@label/.style = {ylabel={Phase (rad)}}}
+ \pgfplotsset{ph@x@label/.style = {xlabel={Phase (rad)}}}
+ \def\ph@scale{1}
+\fi
+\if@hzarg
+ \def\freq@scale{2*pi}
+ \pgfplotsset{freq@label/.style = {xlabel = {Frequency (Hz)}}}
+ \if@pgfarg
+ \pgfplotsset{freq@filter/.style = {x filter/.expression={x-log10(2*pi)}}}
+ \fi
+\fi
+\tikzset{
+ phase unit/.initial={deg},
+ phase unit/.default={deg},
+ phase unit/.is choice,
+ phase unit/deg/.code={
+ \renewcommand{\ph@scale}{180/pi}
+ \pgfplotsset{ph@x@label/.style = {xlabel={Phase (deg)}}}
+ \pgfplotsset{ph@y@label/.style = {ylabel={Phase (deg)}}}
+ },
+ phase unit/rad/.code={
+ \renewcommand{\ph@scale}{1}
+ \pgfplotsset{ph@y@label/.style = {ylabel={Phase (rad)}}}
+ \pgfplotsset{ph@x@label/.style = {xlabel={Phase (rad)}}}
+ },
+ frequency unit/.initial={rad},
+ frequency unit/.default={rad},
+ frequency unit/.is choice,
+ frequency unit/Hz/.code={
+ \renewcommand{\freq@scale}{2*pi}
+ \pgfplotsset{freq@label/.style = {xlabel = {Frequency (Hz)}}}
+ \if@pgfarg
+ \pgfplotsset{freq@filter/.style = {x filter/.expression={x-log10(2*pi)}}}
+ \fi
+ },
+ frequency unit/rad/.code={
+ \renewcommand{\freq@scale}{1}
+ \pgfplotsset{freq@label/.style = {xlabel = {Frequency (rad/s)}}}
+ }
+}
+\def\get@interval@start#1:#2\@nil{#1}
+\def\get@interval@end#1:#2\@nil{#2}
+\newcommand*{\MagK}[2]{(20*log10(abs(#1)))}
+\newcommand*{\MagKAsymp}{\MagK}
+\newcommand*{\MagKLin}{\MagK}
+\newcommand*{\PhK}[2]{((#1<0?-pi:0)*\ph@scale)}
+\newcommand*{\PhKAsymp}{\PhK}
+\newcommand*{\PhKLin}{\PhK}
+\newcommand*{\MagDel}[2]{0}
+\newcommand*{\PhDel}[2]{(-#1*t*\ph@scale)}
+\newcommand*{\MagPole}[2]
+ {(-20*log10(sqrt(\n@pow{#1}{2} + \n@pow{t - (#2)}{2})))}
+\newcommand*{\MagPoleLin}[2]{(t < sqrt(\n@pow{#1}{2} + \n@pow{#2}{2}) ?
+ -20*log10(sqrt(\n@pow{#1}{2} + \n@pow{#2}{2})) :
+ -20*log10(t)
+ )}
+\newcommand*{\MagPoleAsymp}{\MagPoleLin}
+\newcommand*{\PhPole}[2]{((#1 > 0 ? (#2 > 0 ?
+ (\n@mod@p{-atan2((t - (#2)),-(#1))}{2*pi}) :
+ (-atan2((t - (#2)),-(#1)))) :
+ (-atan2((t - (#2)),-(#1))))*\ph@scale)}
+\newcommand*{\PhPoleLin}[2]{
+ ((abs(#1)+abs(#2) == 0 ? -pi/2 :
+ (t < (sqrt(\n@pow{#1}{2} + \n@pow{#2}{2}) /
+ (\n@pow{10}{sqrt(\n@pow{#1}{2}/(\n@pow{#1}{2} + \n@pow{#2}{2}))})) ?
+ (-atan2(-(#2),-(#1))) :
+ (t >= (sqrt(\n@pow{#1}{2} + \n@pow{#2}{2}) *
+ (\n@pow{10}{sqrt(\n@pow{#1}{2}/(\n@pow{#1}{2} + \n@pow{#2}{2}))})) ?
+ (#2>0?(#1>0?3*pi/2:-pi/2):-pi/2) :
+ (-atan2(-(#2),-(#1)) + (log10(t/(sqrt(\n@pow{#1}{2} + \n@pow{#2}{2}) /
+ (\n@pow{10}{sqrt(\n@pow{#1}{2}/(\n@pow{#1}{2} +
+ \n@pow{#2}{2}))}))))*((#2>0?(#1>0?3*pi/2:-pi/2):-pi/2) + atan2(-(#2),-(#1)))/
+ (log10(\n@pow{10}{sqrt((4*\n@pow{#1}{2})/
+ (\n@pow{#1}{2} + \n@pow{#2}{2}))}))))))*\ph@scale)}
+\newcommand*{\PhPoleAsymp}[2]{((t < (sqrt(\n@pow{#1}{2} + \n@pow{#2}{2})) ?
+ (-atan2(-(#2),-(#1))) :
+ (#2>0?(#1>0?3*pi/2:-pi/2):-pi/2))*\ph@scale)}
+\newcommand*{\MagZero}{0-\MagPole}
+\newcommand*{\MagZeroLin}{0-\MagPoleLin}
+\newcommand*{\MagZeroAsymp}{0-\MagPoleAsymp}
+\newcommand*{\PhZero}{0-\PhPole}
+\newcommand*{\PhZeroLin}{0-\PhPoleLin}
+\newcommand*{\PhZeroAsymp}{0-\PhPoleAsymp}
+\newcommand*{\MagCSPoles}[2]{(-20*log10(sqrt(\n@pow{\n@pow{#2}{2}
+ - \n@pow{t}{2}}{2} + \n@pow{2*#1*#2*t}{2})))}
+\newcommand*{\MagCSPolesLin}[2]{(t < #2 ? -40*log10(#2) : - 40*log10(t))}
+\newcommand*{\MagCSPolesAsymp}{\MagCSPolesLin}
+\newcommand*{\PhCSPoles}[2]{((-atan2((2*(#1)*(#2)*t),(\n@pow{#2}{2}
+ - \n@pow{t}{2})))*\ph@scale)}
+\newcommand*{\PhCSPolesLin}[2]{((t < (#2 / (\n@pow{10}{abs(#1)})) ?
+ 0 :
+ (t >= (#2 * (\n@pow{10}{abs(#1)})) ?
+ (#1>0 ? -pi : pi) :
+ (#1>0 ? (-pi*(log10(t*(\n@pow{10}{#1})/#2))/(2*#1)) :
+ (pi*(log10(t*(\n@pow{10}{abs(#1)})/#2))/(2*abs(#1))))))*\ph@scale)}
+\newcommand*{\PhCSPolesAsymp}[2]{((#1>0?(t<#2?0:-pi):(t<#2?0:pi))*\ph@scale)}
+\newcommand*{\MagCSZeros}{0-\MagCSPoles}
+\newcommand*{\MagCSZerosLin}{0-\MagCSPolesLin}
+\newcommand*{\MagCSZerosAsymp}{0-\MagCSPolesAsymp}
+\newcommand*{\PhCSZeros}{0-\PhCSPoles}
+\newcommand*{\PhCSZerosLin}{0-\PhCSPolesLin}
+\newcommand*{\PhCSZerosAsymp}{0-\PhCSPolesAsymp}
+\newcommand*{\MagCSPolesPeak}[3][]{
+ \draw[#1,->] (axis cs:{#3},{-40*log10(#3)}) --
+ (axis cs:{#3},{-40*log10(#3)-20*log10(2*abs(#2))})
+}
+\newcommand*{\MagCSZerosPeak}[3][]{
+ \draw[#1,->] (axis cs:{#3},{40*log10(#3)}) --
+ (axis cs:{#3},{40*log10(#3)+20*log10(2*abs(#2))})
+}
+\newcommand*{\MagSOPoles}[2]{
+ (-20*log10(sqrt(\n@pow{#2 - \n@pow{t}{2}}{2} + \n@pow{#1*t}{2})))}
+\newcommand*{\MagSOPolesLin}[2]{
+ (t < sqrt(abs(#2)) ? -20*log10(abs(#2)) : - 40*log10(t))}
+\newcommand*{\MagSOPolesAsymp}{\MagSOPolesLin}
+\newcommand*{\PhSOPoles}[2]{((-atan2((#1)*t,((#2) - \n@pow{t}{2})))*\ph@scale)}
+\newcommand*{\PhSOPolesLin}[2]{((#2>0 ?
+ \PhCSPolesLin{(#1/(2*sqrt(#2)))}{(sqrt(#2))} :
+ (#1>0 ? -pi : pi)))}
+\newcommand*{\PhSOPolesAsymp}[2]{((#2>0 ?
+ \PhCSPolesAsymp{(#1/(2*sqrt(#2)))}{(sqrt(#2))} :
+ (#1>0 ? -pi : pi)))}
+\newcommand*{\MagSOZeros}{0-\MagSOPoles}
+\newcommand*{\MagSOZerosLin}{0-\MagSOPolesLin}
+\newcommand*{\MagSOZerosAsymp}{0-\MagSOPolesAsymp}
+\newcommand*{\PhSOZeros}{0-\PhSOPoles}
+\newcommand*{\PhSOZerosLin}{0-\PhSOPolesLin}
+\newcommand*{\PhSOZerosAsymp}{0-\PhSOPolesAsymp}
+\newcommand*{\MagSOPolesPeak}[3][]{
+ \draw[#1,->] (axis cs:{sqrt(abs(#3))},{-20*log10(abs(#3))}) --
+ (axis cs:{sqrt(abs(#3))},{-20*log10(abs(#3)) -
+ 20*log10(abs(#2/sqrt(abs(#3))))});
+}
+\newcommand*{\MagSOZerosPeak}[3][]{
+ \draw[#1,->] (axis cs:{sqrt(abs(#3))},{20*log10(abs(#3))}) --
+ (axis cs:{sqrt(abs(#3))},{20*log10(abs(#3)) +
+ 20*log10(abs(#2/sqrt(abs(#3))))});
+}
+\newcommand{\BodeZPK}[4][approx/true]{
+ \parse@opt{#1}
+ \gdef\func@mag{}
+ \gdef\func@ph{}
+ \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]}
+ \temp@cmd
+ \build@ZPK@plot{\func@mag}{\func@ph}{\opt@approx}{#2}
+ \edef\temp@cmd{\noexpand\begin{groupplot}[
+ bode@style,
+ xmin=#3,
+ xmax=#4,
+ domain=#3*\freq@scale:#4*\freq@scale,
+ height=2.5cm,
+ xmode=log,
+ group style = {group size = 1 by 2,vertical sep=0.25cm},
+ \opt@group
+ ]}
+ \temp@cmd
+ \edef\temp@mag@cmd{\noexpand\nextgroupplot [ylabel={Gain (dB)}, xmajorticks=false, \optmag@axes]
+ \noexpand\addplot [freq@filter, variable=t, thick, \optmag@plot]}
+ \edef\temp@ph@cmd{\noexpand\nextgroupplot [ph@y@label, freq@label, \optph@axes]
+ \noexpand\addplot [freq@filter, variable=t, thick, \optph@plot]}
+ \if@pgfarg
+ \temp@mag@cmd {\func@mag};
+ \optmag@commands
+ \temp@ph@cmd {\func@ph};
+ \optph@commands
+ \else
+ \stepcounter{gnuplot@id}
+ \temp@mag@cmd gnuplot [raw gnuplot, gnuplot@prefix]
+ { set table $meta;
+ set dummy t;
+ set logscale x 10;
+ set xrange [#3*\freq@scale:#4*\freq@scale];
+ set samples \pgfkeysvalueof{/pgfplots/samples};
+ plot \func@mag;
+ set table "\bodeplot@prefix\arabic{gnuplot@id}.table";
+ plot "$meta" using ($1/(\freq@scale)):($2);
+ };
+ \optmag@commands
+ \stepcounter{gnuplot@id}
+ \temp@ph@cmd gnuplot [raw gnuplot, gnuplot@prefix]
+ { set table $meta;
+ set dummy t;
+ set logscale x 10;
+ set xrange [#3*\freq@scale:#4*\freq@scale];
+ set samples \pgfkeysvalueof{/pgfplots/samples};
+ plot \func@ph;
+ set table "\bodeplot@prefix\arabic{gnuplot@id}.table";
+ plot "$meta" using ($1/(\freq@scale)):($2);
+ };
+ \optph@commands
+ \fi
+ \end{groupplot}
+ \end{tikzpicture}
+}
+\AtBeginDocument{%
+ \if@babel
+ \let\Orig@BodeZPK\BodeZPK
+ \renewcommand{\BodeZPK}{%
+ \expandafter\shorthandoff\expandafter{\shorthand@list}
+ \BodeZPK@Shorthandoff
+ }
+ \newcommand{\BodeZPK@Shorthandoff}[4][]{%
+ \Orig@BodeZPK[#1]{#2}{#3}{#4}
+ \expandafter\shorthandon\expandafter{\shorthand@list}
+ }
+ \fi
+}
+\newcommand{\BodeTF}[4][]{
+ \parse@opt{#1}
+ \gdef\func@mag{}
+ \gdef\func@ph{}
+ \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]}
+ \temp@cmd
+ \build@TF@plot{\func@mag}{\func@ph}{#2}
+ \edef\temp@cmd{\noexpand\begin{groupplot}[
+ bode@style,
+ xmin=#3,
+ xmax=#4,
+ domain=#3*\freq@scale:#4*\freq@scale,
+ height=2.5cm,
+ xmode=log,
+ group style = {group size = 1 by 2,vertical sep=0.25cm},
+ \opt@group
+ ]}
+ \temp@cmd
+ \edef\temp@mag@cmd{\noexpand\nextgroupplot [ylabel={Gain (dB)}, xmajorticks=false, \optmag@axes]
+ \noexpand\addplot [freq@filter, variable=t, thick, \optmag@plot]}
+ \edef\temp@ph@cmd{\noexpand\nextgroupplot [ph@y@label, freq@label, \optph@axes]
+ \noexpand\addplot [freq@filter, variable=t, thick, \optph@plot]}
+ \if@pgfarg
+ \temp@mag@cmd {\func@mag};
+ \optmag@commands
+ \temp@ph@cmd {\n@mod{\func@ph}{2*pi*\ph@scale}};
+ \optph@commands
+ \else
+ \stepcounter{gnuplot@id}
+ \temp@mag@cmd gnuplot [raw gnuplot, gnuplot@prefix]
+ { set table $meta;
+ set dummy t;
+ set logscale x 10;
+ set xrange [#3*\freq@scale:#4*\freq@scale];
+ set samples \pgfkeysvalueof{/pgfplots/samples};
+ plot \func@mag;
+ set table "\bodeplot@prefix\arabic{gnuplot@id}.table";
+ plot "$meta" using ($1/(\freq@scale)):($2);
+ };
+ \optmag@commands
+ \stepcounter{gnuplot@id}
+ \temp@ph@cmd gnuplot [raw gnuplot, gnuplot@prefix]
+ { set table $meta;
+ set dummy t;
+ set logscale x 10;
+ set trange [#3*\freq@scale:#4*\freq@scale];
+ set samples \pgfkeysvalueof{/pgfplots/samples};
+ plot '+' using (t) : ((\func@ph)/(\ph@scale)) smooth unwrap;
+ set table "\bodeplot@prefix\arabic{gnuplot@id}.table";
+ plot "$meta" using ($1/(\freq@scale)):($2*\ph@scale);
+ };
+ \optph@commands
+ \fi
+ \end{groupplot}
+ \end{tikzpicture}
+}
+\AtBeginDocument{
+ \if@babel
+ \let\Orig@BodeTF\BodeTF
+ \renewcommand{\BodeTF}{%
+ \expandafter\shorthandoff\expandafter{\shorthand@list}
+ \BodeTF@Shorthandoff
+ }
+ \newcommand{\BodeTF@Shorthandoff}[4][]{%
+ \Orig@BodeTF[#1]{#2}{#3}{#4}
+ \expandafter\shorthandon\expandafter{\shorthand@list}
+ }
+ \fi
+}
+\newcommand{\addBodeZPKPlots}[3][true/{}]{
+ \foreach \approx/\opt in {#1} {
+ \gdef\plot@macro{}
+ \gdef\temp@macro{}
+ \ifnum\pdf@strcmp{#2}{phase}=0
+ \build@ZPK@plot{\temp@macro}{\plot@macro}{\approx}{#3}
+ \else
+ \build@ZPK@plot{\plot@macro}{\temp@macro}{\approx}{#3}
+ \fi
+ \if@pgfarg
+ \edef\temp@cmd{\noexpand\addplot [freq@filter, domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, thick, \opt]}
+ \temp@cmd {\plot@macro};
+ \else
+ \stepcounter{gnuplot@id}
+ \edef\temp@cmd{\noexpand\addplot [variable=t, thick, \opt]}
+ \temp@cmd gnuplot [raw gnuplot, gnuplot@prefix]
+ { set table $meta;
+ set dummy t;
+ set logscale x 10;
+ set xrange [\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale];
+ set samples \pgfkeysvalueof{/pgfplots/samples};
+ plot \plot@macro;
+ set table "\bodeplot@prefix\arabic{gnuplot@id}.table";
+ plot "$meta" using ($1/(\freq@scale)):($2);
+ };
+ \fi
+ }
+}
+\newcommand{\addBodeTFPlot}[3][thick]{
+ \gdef\plot@macro{}
+ \gdef\temp@macro{}
+ \ifnum\pdf@strcmp{#2}{phase}=0
+ \build@TF@plot{\temp@macro}{\plot@macro}{#3}
+ \else
+ \build@TF@plot{\plot@macro}{\temp@macro}{#3}
+ \fi
+ \if@pgfarg
+ \ifnum\pdf@strcmp{#2}{phase}=0
+ \edef\temp@cmd{\noexpand\addplot [freq@filter, domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \temp@cmd {\n@mod{\plot@macro}{2*pi}};
+ \else
+ \edef\temp@cmd{\noexpand\addplot [freq@filter, domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \temp@cmd {\plot@macro};
+ \fi
+ \else
+ \stepcounter{gnuplot@id}
+ \ifnum\pdf@strcmp{#2}{phase}=0
+ \addplot [variable=t, #1] gnuplot [raw gnuplot, gnuplot@prefix]
+ { set table $meta;
+ set dummy t;
+ set logscale x 10;
+ set trange [\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale];
+ set samples \pgfkeysvalueof{/pgfplots/samples};
+ plot '+' using (t) : ((\plot@macro)/(\ph@scale)) smooth unwrap;
+ set table "\bodeplot@prefix\arabic{gnuplot@id}.table";
+ plot "$meta" using ($1/(\freq@scale)):($2*\ph@scale);
+ };
+ \else
+ \addplot [variable=t, #1] gnuplot [raw gnuplot, gnuplot@prefix]
+ { set table $meta;
+ set dummy t;
+ set logscale x 10;
+ set xrange [\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale];
+ set samples \pgfkeysvalueof{/pgfplots/samples};
+ plot \plot@macro;
+ set table "\bodeplot@prefix\arabic{gnuplot@id}.table";
+ plot "$meta" using ($1/(\freq@scale)):($2);
+ };
+ \fi
+ \fi
+}
+\newcommand{\addBodeComponentPlot}[2][thick]{
+ \if@pgfarg
+ \edef\temp@cmd{\noexpand\addplot [freq@filter, domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \temp@cmd {#2};
+ \else
+ \stepcounter{gnuplot@id}
+ \addplot [variable=t, #1] gnuplot [raw gnuplot, gnuplot@prefix]
+ { set table $meta;
+ set dummy t;
+ set logscale x 10;
+ set xrange [\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale];
+ set samples \pgfkeysvalueof{/pgfplots/samples};
+ plot #2;
+ set table "\bodeplot@prefix\arabic{gnuplot@id}.table";
+ plot "$meta" using ($1/(\freq@scale)):($2);
+ };
+ \fi
+}
+\AtBeginDocument{%
+ \if@babel
+ \AddToHook{env/BodePhPlot/begin}{\expandafter\shorthandoff\expandafter{\shorthand@list}}
+ \AddToHook{env/BodePhPlot/end}{\expandafter\shorthandon\expandafter{\shorthand@list}}
+ \fi
+}
+\NewDocumentEnvironment{BodePhPlot}{O{}mm+b}{
+ \parse@env@opt{#1}
+ \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]}
+ \temp@cmd
+ \edef\temp@cmd{\noexpand\begin{semilogxaxis}[
+ ph@y@label,
+ freq@label,
+ bode@style,
+ xmin={#2},
+ xmax={#3},
+ domain=#2:#3,
+ height=2.5cm,
+ \unexpanded\expandafter{\opt@axes}
+ ]}
+ \temp@cmd
+ #4
+ \end{semilogxaxis}
+ \end{tikzpicture}
+}{}
+\AtBeginDocument{%
+ \if@babel
+ \AddToHook{env/BodeMagPlot/begin}{\expandafter\shorthandoff\expandafter{\shorthand@list}}
+ \AddToHook{env/BodeMagPlot/end}{\expandafter\shorthandon\expandafter{\shorthand@list}}
+ \fi
+}
+\NewDocumentEnvironment{BodeMagPlot}{O{}mm+b}{
+ \parse@env@opt{#1}
+ \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]}
+ \temp@cmd
+ \edef\temp@cmd{\noexpand\begin{semilogxaxis}[
+ bode@style,
+ freq@label,
+ xmin={#2},
+ xmax={#3},
+ domain=#2:#3,
+ height=2.5cm,
+ ylabel={Gain (dB)},
+ \unexpanded\expandafter{\opt@axes}
+ ]}
+ \temp@cmd
+ #4
+ \end{semilogxaxis}
+ \end{tikzpicture}
+}{}
+\AtBeginDocument{%
+ \if@babel
+ \AddToHook{env/BodePlot/begin}{\expandafter\shorthandoff\expandafter{\shorthand@list}}
+ \AddToHook{env/BodePlot/end}{\expandafter\shorthandon\expandafter{\shorthand@list}}
+ \fi
+}
+\NewDocumentEnvironment{BodePlot}{O{}mm+b}{
+ \parse@env@opt{#1}
+ \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]}
+ \temp@cmd
+ \edef\temp@cmd{\noexpand\begin{semilogxaxis}[
+ bode@style,
+ freq@label,
+ xmin={#2},
+ xmax={#3},
+ domain=#2:#3,
+ height=2.5cm,
+ \unexpanded\expandafter{\opt@axes}
+ ]}
+ \temp@cmd
+ #4
+ \end{semilogxaxis}
+ \end{tikzpicture}
+}{}
+\newcommand*{\add@feature}[3]{
+ \ifcat$\detokenize\expandafter{#1}$
+ \xdef#1{\unexpanded\expandafter{#1 0+#2}}
+ \else
+ \xdef#1{\unexpanded\expandafter{#1+#2}}
+ \fi
+ \foreach \y [count=\n] in #3 {
+ \xdef#1{\unexpanded\expandafter{#1}{\y}}
+ \xdef\Last@LoopValue{\n}
+ }
+ \ifnum\Last@LoopValue=1
+ \xdef#1{\unexpanded\expandafter{#1}{0}}
+ \fi
+}
+\newcommand{\build@ZPK@plot}[4]{
+ \foreach \feature/\values in {#4} {
+ \ifnum\pdf@strcmp{\feature}{z}=0
+ \foreach \z in \values {
+ \ifnum\pdf@strcmp{#3}{linear}=0
+ \add@feature{#2}{\PhZeroLin}{\z}
+ \add@feature{#1}{\MagZeroLin}{\z}
+ \else
+ \ifnum\pdf@strcmp{#3}{asymptotic}=0
+ \add@feature{#2}{\PhZeroAsymp}{\z}
+ \add@feature{#1}{\MagZeroAsymp}{\z}
+ \else
+ \add@feature{#2}{\PhZero}{\z}
+ \add@feature{#1}{\MagZero}{\z}
+ \fi
+ \fi
+ }
+ \fi
+ \ifnum\pdf@strcmp{\feature}{p}=0
+ \foreach \p in \values {
+ \ifnum\pdf@strcmp{#3}{linear}=0
+ \add@feature{#2}{\PhPoleLin}{\p}
+ \add@feature{#1}{\MagPoleLin}{\p}
+ \else
+ \ifnum\pdf@strcmp{#3}{asymptotic}=0
+ \add@feature{#2}{\PhPoleAsymp}{\p}
+ \add@feature{#1}{\MagPoleAsymp}{\p}
+ \else
+ \add@feature{#2}{\PhPole}{\p}
+ \add@feature{#1}{\MagPole}{\p}
+ \fi
+ \fi
+ }
+ \fi
+ \ifnum\pdf@strcmp{\feature}{k}=0
+ \ifnum\pdf@strcmp{#3}{linear}=0
+ \add@feature{#2}{\PhKLin}{\values}
+ \add@feature{#1}{\MagKLin}{\values}
+ \else
+ \ifnum\pdf@strcmp{#3}{asymptotic}=0
+ \add@feature{#2}{\PhKAsymp}{\values}
+ \add@feature{#1}{\MagKAsymp}{\values}
+ \else
+ \add@feature{#2}{\PhK}{\values}
+ \add@feature{#1}{\MagK}{\values}
+ \fi
+ \fi
+ \fi
+ \ifnum\pdf@strcmp{\feature}{d}=0
+ \ifnum\pdf@strcmp{#3}{linear}=0
+ \PackageError {bodeplot} {Linear approximation for pure delays is not
+ supported.} {Plot the true Bode plot using `true' instead of `linear'.}
+ \else
+ \ifnum\pdf@strcmp{#3}{asymptotic}=0
+ \PackageError {bodeplot} {Asymptotic approximation for pure delays is not
+ supported.} {Plot the true Bode plot using `true' instead of `asymptotic'.}
+ \else
+ \ifdim\values pt < 0pt
+ \PackageError {bodeplot} {Delay needs to be a positive number.}
+ \fi
+ \add@feature{#2}{\PhDel}{\values}
+ \add@feature{#1}{\MagDel}{\values}
+ \fi
+ \fi
+ \fi
+ }
+}
+\newcommand{\build@TF@plot}[3]{
+ \gdef\num@real{0}
+ \gdef\num@im{0}
+ \gdef\den@real{0}
+ \gdef\den@im{0}
+ \gdef\loop@delay{0}
+ \foreach \feature/\values in {#3} {
+ \ifnum\pdf@strcmp{\feature}{num}=0
+ \foreach \numcoeff [count=\numpow] in \values {
+ \xdef\num@degree{\numpow}
+ }
+ \foreach \numcoeff [count=\numpow] in \values {
+ \pgfmathtruncatemacro{\currentdegree}{\num@degree-\numpow}
+ \ifnum\currentdegree = 0
+ \xdef\num@real{\num@real+\numcoeff}
+ \else
+ \ifodd\currentdegree
+ \xdef\num@im{\num@im+(\numcoeff*(\n@pow{-1}{(\currentdegree-1)/2})*%
+ (\n@pow{t}{\currentdegree}))}
+ \else
+ \xdef\num@real{\num@real+(\numcoeff*(\n@pow{-1}{(\currentdegree)/2})*%
+ (\n@pow{t}{\currentdegree}))}
+ \fi
+ \fi
+ }
+ \fi
+ \ifnum\pdf@strcmp{\feature}{den}=0
+ \foreach \dencoeff [count=\denpow] in \values {
+ \xdef\den@degree{\denpow}
+ }
+ \foreach \dencoeff [count=\denpow] in \values {
+ \pgfmathtruncatemacro{\currentdegree}{\den@degree-\denpow}
+ \ifnum\currentdegree = 0
+ \xdef\den@real{\den@real+\dencoeff}
+ \else
+ \ifodd\currentdegree
+ \xdef\den@im{\den@im+(\dencoeff*(\n@pow{-1}{(\currentdegree-1)/2})*%
+ (\n@pow{t}{\currentdegree}))}
+ \else
+ \xdef\den@real{\den@real+(\dencoeff*(\n@pow{-1}{(\currentdegree)/2})*%
+ (\n@pow{t}{\currentdegree}))}
+ \fi
+ \fi
+ }
+ \fi
+ \ifnum\pdf@strcmp{\feature}{d}=0
+ \xdef\loop@delay{\values}
+ \fi
+ }
+ \xdef#2{((atan2((\num@im),(\num@real))-atan2((\den@im),%
+ (\den@real))-\loop@delay*t)*(\ph@scale))}
+ \xdef#1{(20*log10(sqrt((\n@pow{\num@real}{2})+(\n@pow{\num@im}{2})))-%
+ 20*log10(sqrt((\n@pow{\den@real}{2})+(\n@pow{\den@im}{2}))))}
+}
+\newcommand{\parse@opt}[1]{
+ \gdef\optmag@axes{}
+ \gdef\optph@axes{}
+ \gdef\optph@plot{}
+ \gdef\optmag@plot{}
+ \gdef\opt@group{}
+ \gdef\opt@approx{}
+ \gdef\optph@commands{}
+ \gdef\optmag@commands{}
+ \gdef\opt@tikz{}
+ \foreach \obj/\typ/\opt in {#1} {
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{plot}=0
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\typ}}{mag}=0
+ \xdef\optmag@plot{\unexpanded\expandafter{\opt}}
+ \else
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\typ}}{ph}=0
+ \xdef\optph@plot{\unexpanded\expandafter{\opt}}
+ \else
+ \xdef\optmag@plot{\unexpanded\expandafter{\opt}}
+ \xdef\optph@plot{\unexpanded\expandafter{\opt}}
+ \fi
+ \fi
+ \else
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{axes}=0
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\typ}}{mag}=0
+ \xdef\optmag@axes{\unexpanded\expandafter{\opt}}
+ \else
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\typ}}{ph}=0
+ \xdef\optph@axes{\unexpanded\expandafter{\opt}}
+ \else
+ \xdef\optmag@axes{\unexpanded\expandafter{\opt}}
+ \xdef\optph@axes{\unexpanded\expandafter{\opt}}
+ \fi
+ \fi
+ \else
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{group}=0
+ \xdef\opt@group{\unexpanded\expandafter{\opt}}
+ \else
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{approx}=0
+ \xdef\opt@approx{\unexpanded\expandafter{\opt}}
+ \else
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{commands}=0
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\typ}}{ph}=0
+ \xdef\optph@commands{\unexpanded\expandafter{\opt}}
+ \else
+ \xdef\optmag@commands{\unexpanded\expandafter{\opt}}
+ \fi
+ \else
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{tikz}=0
+ \xdef\opt@tikz{\unexpanded\expandafter{\opt}}
+ \else
+ \xdef\optmag@plot{\unexpanded\expandafter{\optmag@plot},
+ \unexpanded\expandafter{\obj}}
+ \xdef\optph@plot{\unexpanded\expandafter{\optph@plot},
+ \unexpanded\expandafter{\obj}}
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ \fi
+ }
+}
+\newcommand{\parse@env@opt}[1]{
+ \gdef\opt@axes{}
+ \gdef\opt@tikz{}
+ \foreach \obj/\opt in {#1} {
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{axes}=0
+ \xdef\opt@axes{\unexpanded\expandafter{\opt}}
+ \else
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{tikz}=0
+ \xdef\opt@tikz{\unexpanded\expandafter{\opt}}
+ \else
+ \xdef\opt@axes{\unexpanded\expandafter{\opt@axes},
+ \unexpanded\expandafter{\obj}}
+ \fi
+ \fi
+ }
+}
+\newcommand{\NyquistZPK}[4][]{
+ \parse@N@opt{#1}
+ \gdef\func@mag{}
+ \gdef\func@ph{}
+ \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]}
+ \temp@cmd
+ \build@ZPK@plot{\func@mag}{\func@ph}{}{#2}
+ \edef\temp@cmd{\noexpand\begin{axis}[
+ bode@style,
+ domain=#3*\freq@scale:#4*\freq@scale,
+ height=5cm,
+ xlabel={$\Re$},
+ ylabel={$\Im$},
+ samples=500,
+ \unexpanded\expandafter{\opt@axes}
+ ]}
+ \temp@cmd
+ \addplot [only marks,mark=+,thick,red] (-1 , 0);
+ \edef\temp@cmd{\noexpand\addplot [variable=t, thick, \unexpanded\expandafter{\opt@plot}]}
+ \if@pgfarg
+ \temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale))},
+ {\n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))} );
+ \opt@commands
+ \else
+ \stepcounter{gnuplot@id}
+ \temp@cmd gnuplot [parametric, gnuplot@prefix] {
+ \n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale)),
+ \n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))
+ };
+ \opt@commands
+ \fi
+ \end{axis}
+ \end{tikzpicture}
+}
+\AtBeginDocument{%
+ \if@babel
+ \let\Orig@NyquistZPK\NyquistZPK
+ \renewcommand{\NyquistZPK}{%
+ \expandafter\shorthandoff\expandafter{\shorthand@list}
+ \NyquistZPK@Shorthandoff
+ }
+ \newcommand{\NyquistZPK@Shorthandoff}[4][]{%
+ \Orig@NyquistZPK[#1]{#2}{#3}{#4}
+ \expandafter\shorthandon\expandafter{\shorthand@list}
+ }
+ \fi
+}
+\newcommand{\NyquistTF}[4][]{
+ \parse@N@opt{#1}
+ \gdef\func@mag{}
+ \gdef\func@ph{}
+ \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]}
+ \temp@cmd
+ \build@TF@plot{\func@mag}{\func@ph}{#2}
+ \edef\temp@cmd{\noexpand\begin{axis}[
+ bode@style,
+ domain=#3*\freq@scale:#4*\freq@scale,
+ height=5cm,
+ xlabel={$\Re$},
+ ylabel={$\Im$},
+ samples=500,
+ \unexpanded\expandafter{\opt@axes}
+ ]}
+ \temp@cmd
+ \addplot [only marks, mark=+, thick, red] (-1 , 0);
+ \edef\temp@cmd{\noexpand\addplot [variable=t, thick, \unexpanded\expandafter{\opt@plot}]}
+ \if@pgfarg
+ \temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale))},
+ {\n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))} );
+ \opt@commands
+ \else
+ \stepcounter{gnuplot@id}
+ \temp@cmd gnuplot [parametric, gnuplot@prefix] {
+ \n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale)),
+ \n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))
+ };
+ \opt@commands
+ \fi
+ \end{axis}
+ \end{tikzpicture}
+}
+\AtBeginDocument{%
+ \if@babel
+ \let\Orig@NyquistTF\NyquistTF
+ \renewcommand{\NyquistTF}{%
+ \expandafter\shorthandoff\expandafter{\shorthand@list}
+ \NyquistTF@Shorthandoff
+ }
+ \newcommand{\NyquistTF@Shorthandoff}[4][]{%
+ \Orig@NyquistTF[#1]{#2}{#3}{#4}
+ \expandafter\shorthandon\expandafter{\shorthand@list}
+ }
+ \fi
+}
+\newcommand{\addNyquistZPKPlot}[2][]{
+ \gdef\func@mag{}
+ \gdef\func@ph{}
+ \build@ZPK@plot{\func@mag}{\func@ph}{}{#2}
+ \if@pgfarg
+ \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale))},
+ {\n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))} );
+ \else
+ \stepcounter{gnuplot@id}
+ \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \temp@cmd gnuplot [parametric, gnuplot@prefix] {
+ \n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale)),
+ \n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))
+ };
+ \fi
+}
+\newcommand{\addNyquistTFPlot}[2][]{
+ \gdef\func@mag{}
+ \gdef\func@ph{}
+ \build@TF@plot{\func@mag}{\func@ph}{#2}
+ \if@pgfarg
+ \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale))},
+ {\n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))} );
+ \else
+ \stepcounter{gnuplot@id}
+ \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \temp@cmd gnuplot [parametric, gnuplot@prefix]{
+ \n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale)),
+ \n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))
+ };
+ \fi
+}
+\AtBeginDocument{%
+ \if@babel
+ \AddToHook{env/NyquistPlot/begin}{\expandafter\shorthandoff\expandafter{\shorthand@list}}
+ \AddToHook{env/NyquistPlot/end}{\expandafter\shorthandon\expandafter{\shorthand@list}}
+ \fi
+}
+\NewDocumentEnvironment{NyquistPlot}{O{}mm+b}{
+ \parse@env@opt{#1}
+ \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]}
+ \temp@cmd
+ \edef\temp@cmd{\noexpand\begin{axis}[
+ bode@style,
+ height=5cm,
+ domain=#2:#3,
+ xlabel={$\Re$},
+ ylabel={$\Im$},
+ \unexpanded\expandafter{\opt@axes}
+ ]}
+ \temp@cmd
+ \addplot [only marks,mark=+,thick,red] (-1 , 0);
+ #4
+ \end{axis}
+ \end{tikzpicture}
+}{}
+\newcommand{\parse@N@opt}[1]{
+ \gdef\opt@axes{}
+ \gdef\opt@plot{}
+ \gdef\opt@commands{}
+ \gdef\opt@tikz{}
+ \foreach \obj/\opt in {#1} {
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{axes}=0
+ \xdef\opt@axes{\unexpanded\expandafter{\opt}}
+ \else
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{plot}=0
+ \xdef\opt@plot{\unexpanded\expandafter{\opt}}
+ \else
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{commands}=0
+ \xdef\opt@commands{\unexpanded\expandafter{\opt}}
+ \else
+ \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{tikz}=0
+ \xdef\opt@tikz{\unexpanded\expandafter{\opt}}
+ \else
+ \xdef\opt@plot{\unexpanded\expandafter{\opt@plot},
+ \unexpanded\expandafter{\obj}}
+ \fi
+ \fi
+ \fi
+ \fi
+ }
+}
+\newcommand{\NicholsZPK}[4][]{
+ \parse@N@opt{#1}
+ \gdef\func@mag{}
+ \gdef\func@ph{}
+ \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]}
+ \temp@cmd
+ \build@ZPK@plot{\func@mag}{\func@ph}{}{#2}
+ \edef\temp@cmd{\noexpand\begin{axis}[
+ ph@x@label,
+ bode@style,
+ domain=#3*\freq@scale:#4*\freq@scale,
+ height=5cm,
+ ylabel={Gain (dB)},
+ samples=500,
+ \unexpanded\expandafter{\opt@axes}
+ ]}
+ \temp@cmd
+ \edef\temp@cmd{\noexpand\addplot [variable=t,thick,\opt@plot]}
+ \if@pgfarg
+ \temp@cmd ( {\func@ph} , {\func@mag} );
+ \opt@commands
+ \else
+ \stepcounter{gnuplot@id}
+ \temp@cmd gnuplot [raw gnuplot, gnuplot@prefix]
+ { set table $meta;
+ set logscale x 10;
+ set dummy t;
+ set samples \pgfkeysvalueof{/pgfplots/samples};
+ set trange [#3*\freq@scale:#4*\freq@scale];
+ plot '+' using (\func@mag) : ((\func@ph)/(\ph@scale));
+ unset logscale x;
+ set table "\bodeplot@prefix\arabic{gnuplot@id}.table";
+ plot "$meta" using ($2*\ph@scale):($1);
+ };
+ \opt@commands
+ \fi
+ \end{axis}
+ \end{tikzpicture}
+}
+\AtBeginDocument{%
+ \if@babel
+ \let\Orig@NicholsZPK\NicholsZPK
+ \renewcommand{\NicholsZPK}{%
+ \expandafter\shorthandoff\expandafter{\shorthand@list}
+ \NicholsZPK@Shorthandoff
+ }
+ \newcommand{\NicholsZPK@Shorthandoff}[4][]{%
+ \Orig@NicholsZPK[#1]{#2}{#3}{#4}
+ \expandafter\shorthandon\expandafter{\shorthand@list}
+ }
+ \fi
+}
+\newcommand{\NicholsTF}[4][]{
+ \parse@N@opt{#1}
+ \gdef\func@mag{}
+ \gdef\func@ph{}
+ \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]}
+ \temp@cmd
+ \build@TF@plot{\func@mag}{\func@ph}{#2}
+ \edef\temp@cmd{\noexpand\begin{axis}[
+ ph@x@label,
+ bode@style,
+ domain=#3*\freq@scale:#4*\freq@scale,
+ height=5cm,
+ ylabel={Gain (dB)},
+ samples=500,
+ \unexpanded\expandafter{\opt@axes}
+ ]}
+ \temp@cmd
+ \edef\temp@cmd{\noexpand\addplot [variable=t,thick, \opt@plot]}
+ \if@pgfarg
+ \temp@cmd ( {\n@mod{\func@ph}{2*pi*\ph@scale}} , {\func@mag} );
+ \opt@commands
+ \else
+ \stepcounter{gnuplot@id}
+ \temp@cmd gnuplot [raw gnuplot, gnuplot@prefix]
+ { set table $meta1;
+ set logscale x 10;
+ set dummy t;
+ set samples \pgfkeysvalueof{/pgfplots/samples};
+ set trange [#3*\freq@scale:#4*\freq@scale];
+ plot '+' using (\func@mag) : ((\func@ph)/(\ph@scale));
+ unset logscale x;
+ set table $meta2;
+ plot "$meta1" using ($1):($2) smooth unwrap;
+ set table "\bodeplot@prefix\arabic{gnuplot@id}.table";
+ plot "$meta2" using ($2*\ph@scale):($1);
+ };
+ \opt@commands
+ \fi
+ \end{axis}
+ \end{tikzpicture}
+}
+\AtBeginDocument{
+ \if@babel
+ \let\Orig@NicholsTF\NicholsTF
+ \renewcommand{\NicholsTF}{%
+ \expandafter\shorthandoff\expandafter{\shorthand@list}
+ \NicholsTF@Shorthandoff
+ }
+ \newcommand{\NicholsTF@Shorthandoff}[4][]{%
+ \Orig@NicholsTF[#1]{#2}{#3}{#4}
+ \expandafter\shorthandon\expandafter{\shorthand@list}
+ }
+ \AddToHook{env/NicholsChart/begin}{\expandafter\shorthandoff\expandafter{\shorthand@list}}
+ \AddToHook{env/NicholsChart/end}{\expandafter\shorthandon\expandafter{\shorthand@list}}
+ \fi
+}
+\NewDocumentEnvironment{NicholsChart}{O{}mm+b}{
+ \parse@env@opt{#1}
+ \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]}
+ \temp@cmd
+ \edef\temp@cmd{\noexpand\begin{axis}[
+ ph@x@label,
+ bode@style,
+ domain=#2:#3,
+ height=5cm,
+ ylabel={Gain (dB)},
+ \unexpanded\expandafter{\opt@axes}
+ ]}
+ \temp@cmd
+ #4
+ \end{axis}
+ \end{tikzpicture}
+}{}
+\newcommand{\addNicholsZPKChart}[2][]{
+ \gdef\func@mag{}
+ \gdef\func@ph{}
+ \build@ZPK@plot{\func@mag}{\func@ph}{}{#2}
+ \if@pgfarg
+ \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \temp@cmd ( {\func@ph} , {\func@mag} );
+ \else
+ \stepcounter{gnuplot@id}
+ \addplot [#1] gnuplot [raw gnuplot, gnuplot@prefix]
+ { set table $meta;
+ set logscale x 10;
+ set dummy t;
+ set samples \pgfkeysvalueof{/pgfplots/samples};
+ set trange [\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale];
+ plot '+' using (\func@mag) : ((\func@ph)/(\ph@scale));
+ unset logscale x;
+ set table "\bodeplot@prefix\arabic{gnuplot@id}.table";
+ plot "$meta" using ($2*\ph@scale):($1);
+ };
+ \fi
+}
+\newcommand{\addNicholsTFChart}[2][]{
+ \gdef\func@mag{}
+ \gdef\func@ph{}
+ \build@TF@plot{\func@mag}{\func@ph}{#2}
+ \if@pgfarg
+ \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \temp@cmd ( {\n@mod{\func@ph}{2*pi*\ph@scale}} , {\func@mag} );
+ \else
+ \stepcounter{gnuplot@id}
+ \addplot [#1] gnuplot [raw gnuplot, gnuplot@prefix]
+ { set table $meta1;
+ set logscale x 10;
+ set dummy t;
+ set samples \pgfkeysvalueof{/pgfplots/samples};
+ set trange [\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale];
+ plot '+' using (\func@mag) : ((\func@ph)/(\ph@scale));
+ unset logscale x;
+ set table $meta2;
+ plot "$meta1" using ($1):($2) smooth unwrap;
+ set table "\bodeplot@prefix\arabic{gnuplot@id}.table";
+ plot "$meta2" using ($2*\ph@scale):($1);
+ };
+ \fi
+}
+\endinput
+%%
+%% End of file `bodeplot.sty'.
diff --git a/graphics/pgf/contrib/bodeplot/bodeplot.dtx b/graphics/pgf/contrib/bodeplot/bodeplot.dtx
index d9964e4a1b..09031ab3f9 100644
--- a/graphics/pgf/contrib/bodeplot/bodeplot.dtx
+++ b/graphics/pgf/contrib/bodeplot/bodeplot.dtx
@@ -16,8 +16,10 @@
% \fi
%
% \iffalse
-%<package>\NeedsTeXFormat{LaTeX2e}[2006/05/20]
-%<package>\ProvidesPackage{bodeplot}
+%<package>\NeedsTeXFormat{LaTeX2e}[2018/04/01]
+%<package>\DeclareRelease{}{2024-02-06}{bodeplot-2024-02-06.sty}
+%<package>\DeclareCurrentRelease{}{2024/04/18}
+%<package>\ProvidesPackage{bodeplot}[2024/04/18 v1.2 Generate Bode, Nichols, and Nyquist plots]
%<package>\RequirePackage{pdftexcmds}
%<package>\RequirePackage{ifplatform}
%<package>\RequirePackage{xparse}
@@ -69,7 +71,7 @@
%</driver>
% \fi
%
-% \CheckSum{1858}
+% \CheckSum{1857}
%
% \changes{v1.0}{2021/10/25}{Initial release}
% \changes{v1.0.4}{2021/11/05}{Fixed unintended optional argument macro expansion}
@@ -80,11 +82,12 @@
% \changes{v1.1.0}{2022/07/06}{Fixed phase wrapping in gnuplot mode}
% \changes{v1.1.1}{2022/07/31}{Enable Hz and rad units}
% \changes{v1.1.7}{2024/02/06}{Detect and turn off shorthands to improve `babel' compatibility}
+% \changes{v1.2}{2024/04/18}{Removed global option to process pgf commands in radians}
%
% \GetFileInfo{bodeplot.sty}
% \DoNotIndex{\newcommand,\xdef,\gdef,\def,\edef,\addplot,\approx,\arabic,\opt,\typ,\obj,\else,\if@pgfarg,\if@Hzarg,\if@radarg,\if@declutterarg,\if@babel,\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\\version 1.1.7}
+% \title{The \textsf{bodeplot} package\\version 1.2}
% \author{Rushikesh Kamalapurkar \\ \texttt{rlkamalapurkar@gmail.com}}
%
% \maketitle
@@ -105,6 +108,7 @@
% Since version 1.0.8, the |bodeplot| package places all |gnuplot| temporary files in the working directory. The package option |declutter| restores the original behavior where the temporary files are placed in a folder called |gnuplot|.
% \subsection{Limitations}
% \begin{itemize}
+% \item Before version 1.2, in |pgf| mode, the package set |trig format plots| to |rad| globally. Version 1.2 onwards, this option is passed to each |addplot| command individually so that it does not affect other plots in the document. To roll back to the pre-1.2 behavior, load the package with |\usepackage[pgf]{bodeplot}[=2024-02-06]|.
% \item In |pgf| mode, Bode phase plots and Nichols charts in TF form wrap angles so that they are always between -180 and 180$^\circ$ or $-\pi$ and $-\pi$ radian. As such, these plots will show phase wrapping discontinuities. Since v1.1.1, in |gnuplot| mode, the package uses the |smooth unwrap| filter to correct wrapping discontinuities. As of now, I have not found a way to do this in |pgf| mode, any merge requests or ideas you may have are welcome! Since v1.1.4, you can redefine the |n@mod| macro using the commands |\makeatletter\renewcommand{\n@mod}{\n@mod@p}\makeatother| to wrap the phase between 0 and 360$^\circ$ or $0$ and $2\pi$ radian. The commands |\makeatletter\renewcommand{\n@mod}{\n@mod@n}\makeatother| will wrap the phase between -360 and 0$^\circ$ or $-2\pi$ and $0$ radian.
% \item Use of the |declutter| option with other directory management tools such as a |tikzexternalize| prefix is not recommended.
% \end{itemize}
@@ -602,7 +606,7 @@ Nyquist plots with additional commands, using two different macros
% \DescribeMacro{\addBodeComponentPlot}
% |\addBodeComponentPlot|\oarg{plot-options}\marg{plot-command}
%
-% \noindent Generates a single parametric function corresponding to the mandatory argument |plot-command| and passes it to the |\addplot| macro. The plot command can be any parametric function that uses |t| as the independent variable. The parametric function must be |gnuplot| compatible (or |pgfplots| compatible if the package is loaded using the |pgf| option). The intended use of this macro is to plot the parametric functions generated using the basic component macros described in Section \ref{sec:BasicComponents} below.
+% \noindent Generates a single parametric function corresponding to the mandatory argument |plot-command| and passes it to the |\addplot| macro. The plot command can be any parametric function that uses |t| as the independent variable. The parametric function must be |gnuplot| compatible (or |pgfplots| compatible if the package is loaded using the |pgf| option, \textbf{with angles passed to trigonometric functions in radian}). The intended use of this macro is to plot the parametric functions generated using the basic component macros described in Section \ref{sec:BasicComponents} below.
%
% \subsubsection{Basic components up to first order\label{sec:BasicComponents}}
%
@@ -839,6 +843,7 @@ Nyquist plots with additional commands, using two different macros
% \changes{v1.0.3}{2021/11/03}{Added jobname to gnuplot prefix}
% \changes{v1.0.8}{2022/07/06}{Fixed issue \#6}
% \changes{v1.1.4}{2023/10/12}{Changed phase wrapping in pgf mode}
+% \changes{v1.2}{2024/04/18}{Removed global option to process pgf commands in radians}
% We start by processing the class options.
% \begin{macrocode}
\newif\if@pgfarg\@pgfargfalse
@@ -866,9 +871,6 @@ Nyquist plots with additional commands, using two different macros
\newcommand{\n@mod@n}[2]{(#1)-((floor((#1)/(#2))+1)*(#2))}
\if@pgfarg
\newcommand{\n@pow}[2]{(#1)^(#2)}
- \pgfplotsset{
- trig format plots=rad
- }
\else
\newcommand{\n@pow}[2]{(#1)**(#2)}
% \end{macrocode}
@@ -1295,7 +1297,7 @@ Nyquist plots with additional commands, using two different macros
\edef\temp@mag@cmd{\noexpand\nextgroupplot [ylabel={Gain (dB)}, xmajorticks=false, \optmag@axes]
\noexpand\addplot [freq@filter, variable=t, thick, \optmag@plot]}
\edef\temp@ph@cmd{\noexpand\nextgroupplot [ph@y@label, freq@label, \optph@axes]
- \noexpand\addplot [freq@filter, variable=t, thick, \optph@plot]}
+ \noexpand\addplot [freq@filter, variable=t, thick, trig format plots=rad, \optph@plot]}
\if@pgfarg
\temp@mag@cmd {\func@mag};
\optmag@commands
@@ -1375,7 +1377,7 @@ Nyquist plots with additional commands, using two different macros
\edef\temp@mag@cmd{\noexpand\nextgroupplot [ylabel={Gain (dB)}, xmajorticks=false, \optmag@axes]
\noexpand\addplot [freq@filter, variable=t, thick, \optmag@plot]}
\edef\temp@ph@cmd{\noexpand\nextgroupplot [ph@y@label, freq@label, \optph@axes]
- \noexpand\addplot [freq@filter, variable=t, thick, \optph@plot]}
+ \noexpand\addplot [freq@filter, variable=t, thick, trig format plots=rad, \optph@plot]}
\if@pgfarg
\temp@mag@cmd {\func@mag};
\optmag@commands
@@ -1441,7 +1443,7 @@ Nyquist plots with additional commands, using two different macros
\build@ZPK@plot{\plot@macro}{\temp@macro}{\approx}{#3}
\fi
\if@pgfarg
- \edef\temp@cmd{\noexpand\addplot [freq@filter, domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, thick, \opt]}
+ \edef\temp@cmd{\noexpand\addplot [freq@filter, domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, thick, trig format plots=rad, \opt]}
\temp@cmd {\plot@macro};
\else
\stepcounter{gnuplot@id}
@@ -1474,7 +1476,7 @@ Nyquist plots with additional commands, using two different macros
\fi
\if@pgfarg
\ifnum\pdf@strcmp{#2}{phase}=0
- \edef\temp@cmd{\noexpand\addplot [freq@filter, domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \edef\temp@cmd{\noexpand\addplot [freq@filter, domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, trig format plots=rad, #1]}
\temp@cmd {\n@mod{\plot@macro}{2*pi}};
\else
\edef\temp@cmd{\noexpand\addplot [freq@filter, domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
@@ -1510,11 +1512,11 @@ Nyquist plots with additional commands, using two different macros
% \end{macrocode}
%\end{macro}
% \begin{macro}{\addBodeComponentPlot}
-% This macro is designed to issue a single |\addplot| macro capable of plotting linear combinations of the basic components described in Section \ref{sec:BasicComponents}. The only work to do here is to handle the |pgf| package option.\changes{v1.1.1}{2022/07/31}{Enabled `Hz' and `rad' units for frequency and phase, respectively}\changes{v1.1.3}{2022/11/02}{Changed implementation to respect user-supplied domain}
+% This macro is designed to create a single |\addplot| macro capable of plotting linear combinations of the basic components described in Section \ref{sec:BasicComponents}. The only work to do here is to handle the |pgf| package option.\changes{v1.1.1}{2022/07/31}{Enabled `Hz' and `rad' units for frequency and phase, respectively}\changes{v1.1.3}{2022/11/02}{Changed implementation to respect user-supplied domain}
% \begin{macrocode}
\newcommand{\addBodeComponentPlot}[2][thick]{
\if@pgfarg
- \edef\temp@cmd{\noexpand\addplot [freq@filter, domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \edef\temp@cmd{\noexpand\addplot [freq@filter, domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, trig format plots=rad, #1]}
\temp@cmd {#2};
\else
\stepcounter{gnuplot@id}
@@ -1884,7 +1886,7 @@ Nyquist plots with additional commands, using two different macros
]}
\temp@cmd
\addplot [only marks,mark=+,thick,red] (-1 , 0);
- \edef\temp@cmd{\noexpand\addplot [variable=t, thick, \unexpanded\expandafter{\opt@plot}]}
+ \edef\temp@cmd{\noexpand\addplot [variable=t, thick, trig format plots=rad, \unexpanded\expandafter{\opt@plot}]}
\if@pgfarg
\temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale))},
{\n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))} );
@@ -1939,7 +1941,7 @@ Nyquist plots with additional commands, using two different macros
]}
\temp@cmd
\addplot [only marks, mark=+, thick, red] (-1 , 0);
- \edef\temp@cmd{\noexpand\addplot [variable=t, thick, \unexpanded\expandafter{\opt@plot}]}
+ \edef\temp@cmd{\noexpand\addplot [variable=t, thick, trig format plots=rad, \unexpanded\expandafter{\opt@plot}]}
\if@pgfarg
\temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale))},
{\n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))} );
@@ -1981,7 +1983,7 @@ Nyquist plots with additional commands, using two different macros
\gdef\func@ph{}
\build@ZPK@plot{\func@mag}{\func@ph}{}{#2}
\if@pgfarg
- \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, trig format plots=rad, #1]}
\temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale))},
{\n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))} );
\else
@@ -2003,7 +2005,7 @@ Nyquist plots with additional commands, using two different macros
\gdef\func@ph{}
\build@TF@plot{\func@mag}{\func@ph}{#2}
\if@pgfarg
- \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, trig format plots=rad, #1]}
\temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale))},
{\n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))} );
\else
@@ -2107,7 +2109,7 @@ Nyquist plots with additional commands, using two different macros
\unexpanded\expandafter{\opt@axes}
]}
\temp@cmd
- \edef\temp@cmd{\noexpand\addplot [variable=t,thick,\opt@plot]}
+ \edef\temp@cmd{\noexpand\addplot [variable=t, thick, trig format plots=rad, \opt@plot]}
\if@pgfarg
\temp@cmd ( {\func@ph} , {\func@mag} );
\opt@commands
@@ -2159,7 +2161,7 @@ Nyquist plots with additional commands, using two different macros
\unexpanded\expandafter{\opt@axes}
]}
\temp@cmd
- \edef\temp@cmd{\noexpand\addplot [variable=t,thick, \opt@plot]}
+ \edef\temp@cmd{\noexpand\addplot [variable=t, thick, trig format plots=rad, \opt@plot]}
\if@pgfarg
\temp@cmd ( {\n@mod{\func@ph}{2*pi*\ph@scale}} , {\func@mag} );
\opt@commands
@@ -2220,7 +2222,7 @@ Nyquist plots with additional commands, using two different macros
\gdef\func@ph{}
\build@ZPK@plot{\func@mag}{\func@ph}{}{#2}
\if@pgfarg
- \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, trig format plots=rad, #1]}
\temp@cmd ( {\func@ph} , {\func@mag} );
\else
\stepcounter{gnuplot@id}
@@ -2242,7 +2244,7 @@ Nyquist plots with additional commands, using two different macros
\gdef\func@ph{}
\build@TF@plot{\func@mag}{\func@ph}{#2}
\if@pgfarg
- \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, #1]}
+ \edef\temp@cmd{\noexpand\addplot [domain=\freq@scale*\pgfkeysvalueof{/pgfplots/domain}*\freq@scale, variable=t, trig format plots=rad, #1]}
\temp@cmd ( {\n@mod{\func@ph}{2*pi*\ph@scale}} , {\func@mag} );
\else
\stepcounter{gnuplot@id}
diff --git a/graphics/pgf/contrib/bodeplot/bodeplot.ins b/graphics/pgf/contrib/bodeplot/bodeplot.ins
index 1a80024f83..9ac5268913 100644
--- a/graphics/pgf/contrib/bodeplot/bodeplot.ins
+++ b/graphics/pgf/contrib/bodeplot/bodeplot.ins
@@ -1,5 +1,5 @@
%%
-%% Copyright (C) 2021 by Rushikesh Kamalapurkar
+%% Copyright (C) 2021-2024 by Rushikesh Kamalapurkar
%%
%% This file may be distributed and/or modified under the
%% conditions of the LaTeX Project Public License, either
@@ -16,7 +16,7 @@
\usedir{tex/latex/bodeplot}
\preamble
This is a generated file.
-Copyright (C) 2021 by Rushikesh Kamalapurkar
+Copyright (C) 2021-2024 by Rushikesh Kamalapurkar
This file may be distributed and/or modified under the
conditions of the LaTeX Project Public License, either
version 1.3c of this license or (at your option) any later
diff --git a/graphics/pgf/contrib/bodeplot/bodeplot.pdf b/graphics/pgf/contrib/bodeplot/bodeplot.pdf
index 34a34a224a..4e0bf79b67 100644
--- a/graphics/pgf/contrib/bodeplot/bodeplot.pdf
+++ b/graphics/pgf/contrib/bodeplot/bodeplot.pdf
Binary files differ