From 2aa608cd9808e84c462362be9eb92a98a1b79e4d Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Fri, 25 Jul 2014 21:05:22 +0000 Subject: dsptricks (25jul14) git-svn-id: svn://tug.org/texlive/trunk@34724 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/doc/latex/dsptricks/README | 16 + .../doc/latex/dsptricks/dspTricksManual.pdf | Bin 0 -> 212782 bytes .../doc/latex/dsptricks/dspTricksManual.tex | 921 +++++++++++++++++ .../texmf-dist/tex/latex/dsptricks/dspblocks.sty | 116 +++ .../tex/latex/dsptricks/dspfunctions.sty | 258 +++++ .../texmf-dist/tex/latex/dsptricks/dsptricks.sty | 1071 ++++++++++++++++++++ Master/tlpkg/bin/tlpkg-ctan-check | 2 +- Master/tlpkg/tlpsrc/collection-pstricks.tlpsrc | 1 + Master/tlpkg/tlpsrc/dsptricks.tlpsrc | 0 9 files changed, 2384 insertions(+), 1 deletion(-) create mode 100644 Master/texmf-dist/doc/latex/dsptricks/README create mode 100644 Master/texmf-dist/doc/latex/dsptricks/dspTricksManual.pdf create mode 100644 Master/texmf-dist/doc/latex/dsptricks/dspTricksManual.tex create mode 100644 Master/texmf-dist/tex/latex/dsptricks/dspblocks.sty create mode 100644 Master/texmf-dist/tex/latex/dsptricks/dspfunctions.sty create mode 100644 Master/texmf-dist/tex/latex/dsptricks/dsptricks.sty create mode 100644 Master/tlpkg/tlpsrc/dsptricks.tlpsrc diff --git a/Master/texmf-dist/doc/latex/dsptricks/README b/Master/texmf-dist/doc/latex/dsptricks/README new file mode 100644 index 00000000000..8252f6138a8 --- /dev/null +++ b/Master/texmf-dist/doc/latex/dsptricks/README @@ -0,0 +1,16 @@ +DSPTricks (with DSPFunctios and DSPBlocks) +v1.0 - July 2014 + +(c) Paolo Prandoni, 2014, paolo.prandoni@epfl.ch + +The package DSPTricks is a set of LaTeX macros +(based on PSTricks) for plotting the kind of graphs +and figures that are usually employed in digital +signal processing publications. DSPTricks provides +facilities for standard discrete-time "lollipop" plots, +continuous-time and frequency plots, and pole-zero plots. +The companion package DSPFunctions provides macros +to compute frequency responses and DFTs, while the +package DSPBlocks supports DSP block diagrams. + +See also www.sp4comm.org \ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/dsptricks/dspTricksManual.pdf b/Master/texmf-dist/doc/latex/dsptricks/dspTricksManual.pdf new file mode 100644 index 00000000000..ae5f6ebc7db Binary files /dev/null and b/Master/texmf-dist/doc/latex/dsptricks/dspTricksManual.pdf differ diff --git a/Master/texmf-dist/doc/latex/dsptricks/dspTricksManual.tex b/Master/texmf-dist/doc/latex/dsptricks/dspTricksManual.tex new file mode 100644 index 00000000000..2b733a9faa1 --- /dev/null +++ b/Master/texmf-dist/doc/latex/dsptricks/dspTricksManual.tex @@ -0,0 +1,921 @@ +% User manual for the DSPTricks package +% (c) Paolo Prandoni, 2014 +% v1.0, July 2014 +% For more information, authors@sp4comm.org + +\documentclass[a4paper,10pt]{ltxdoc} +\usepackage{float} +\usepackage{fancyvrb} +\usepackage{enumitem} +\usepackage[utopia]{mathdesign} +\usepackage{url} +\usepackage{dsptricks,dspfunctions,dspblocks} + + +\def\dspt{{DSPTricks}} +\def\dspf{{DSPFunctions}} +\def\dspb{{DSPBlocks}} +\def\psTricks{{PSTricks}} + +\setlength\parindent{0pt} + +\newenvironment{optList}{% + \begin{description}[labelindent=2em,font=\rm,itemsep=-1mm,leftmargin=2cm]}% + {\end{description}} + +\def\vblock{\begin{Verbatim}[frame=single,% + numbers=left,numbersep=2pt,% + fontsize=\footnotesize,% + xleftmargin=0mm,xrightmargin=0mm]} +\def\evblock{\end{Verbatim}} +\def\vopts{frame=single,% + numbers=left,numbersep=2pt,% + fontsize=\footnotesize,% + xleftmargin=15mm,xrightmargin=6mm} + +\newenvironment{centerfig}{% + \begin{figure}[H] + \begin{center}}{ + \end{center} + \end{figure}} + +\begin{document} + +\title{\dspt \\ A Set of Macros for Digital Signal Processing Plots} +\author{Paolo Prandoni} +\date{} +\maketitle + + + +The package \dspt\ is a set of \LaTeX\ macros for plotting the kind of graphs and figures that are usually employed in digital signal processing publications\footnote{The original macros have been written by the author while working on the manuscript for~\cite{PV}.}; the package relies on \psTricks~\cite{TVZ93,HV} to generate its graphic output. +%\footnote{Please note that these macros have been written rather quickly and chiefly for personal use. Use at your own risk and caveat emptor.} + +The basic \dspt\ plot is a boxed chart displaying a discrete-time or a continuous-time signal, or a superposition of both; discrete-time signals are plotted using the ``lollipop'' formalism while continuous-time functions are rendered as smooth curves. Other types of plots that commonly occur in the signal processing literature, and for which \dspt\ offers macros, are frequency plots and pole-zero plots. The companion package \dspf\ defines some signals commonly used in basic signal processing in terms of PostScript primitives, while the package \dspb\ provides a set of macros to design simple signal processing block diagrams. + + + +\section{Drawing Signals} + +Signal plots in \dspt\ are defined by a Cartesian grid enclosed by a box; there are three fundamental types of plots: +\begin{itemize} + \item discrete-time plots, + \item continuous-time plots, + \item frequency-domain plots; +\end{itemize} +discrete- and continuous-time plots can be mixed, whereas frequency-domain plots involve a re-labeling of the horizontal axis in trigonometric units. + + +\subsection{The {\tt dspPlot} environment} +Data plots are defined by the {\tt dspPlot} environment as \DescribeEnv{dspPlot} +\begin{quote} + |\begin{dspPlot}|\oarg{options}\marg{xmin, xmax}\marg{ymin, ymax} \\ + ... \\ + |\end{dspPlot}| +\end{quote} +This sets up a data plot with the horizontal axis spanning the \meta{xmin}-\meta{xmax} interval and with the vertical axis spanning the \meta{ymin}-\meta{ymax} interval. The following options are available for all data plots: + +\begin{optList} + \item[|width|=\meta{dim}]: width of the plot (using any units) + \item[|height|=\meta{dim}]: height of the plot. Width and height specify the size of the active plot area, i.e., of the \emph{boxed region} of the cartesian plane specified by the $x$ and $y$ ranges for the plot. This is possibly augmented by the space required by the optional labels and axis marks. You can set the default size for a plot by setting the \DescribeEnv{dspW, dspH} |\dspW| and |\dspH| lengths at the beginning of your document +\end{optList} + +\begin{optList} + \item[|xtype| = |time| $\mid$ |freq| ]: type of plot: time domain (default) or digital frequency plot +\end{optList} + +\begin{optList} + \item[|xticks| = |auto| $\mid$ |custom| $\mid$ |none| $\mid$ \meta{step}]: labeling of the horizontal axis + \item[|yticks| = |auto| $\mid$ |custom| $\mid$ |none| $\mid$ \meta{step}]: labeling of the vertical axis. When the option specifies a numeric value \meta{step}, that will be the spacing between two consecutive ticks on the axis\footnote{For digital frequency plots, |xticks| has a different meaning; see Section~\ref{freqPlots} for details.}. When |auto| is selected, the spacing will be computed automatically as a function of the axis range. When |none| is selected, no ticks will be drawn. When |custom| is selected, no ticks will be drawn but the plot will include the appropriate spacing for ticks to be drawn later via the |\dspCustomTicks| macro. + \item[|sidegap| = \meta{gap}]: extra space (in horizontal units) to the left and the right of the $x$-axis range. Useful in discrete-time plots not to have stems overlapping the plot's frame. By default, it's automatically determined as a function of the range; use a value of zero to eliminate the side gap. + \item[|xout| = |true| $\mid$ |false|]: normally, ticks and tick labels for the horizontal axis are placed on the axis, which may be inside the box; set this option to |true| if you want to place the ticks on the lower edge of the box in all cases. + \item[|inticks| = |true| $\mid$ |false|]: x-axis ticks are normally extending downwards; by setting this option to |true| ticks will be pointing upwards, i.e. they will be inside the plot box even when the x-axis coincides with the bottom of the box. +\end{optList} + +\begin{optList} + \item[|xlabel| = \meta{label} ]: label for the horizontal axis; placed outside the plot box + \item[|ylabel| = \meta{label} ]: label for the vertical axis; placed outside the plot box, on the left + \item[|rlabel| = \meta{label} ]: additional label for the vertical axis; placed outside the plot box on the right +\end{optList} + + + + +Within a |dspPlot| environment you can use the plotting commands described in the next sections, as well as any \psTricks\ command; in the latter case, the \psTricks\ values for |xunit| and |yunit| are scaled to the axes (i.e., they correspond to the cartesian values of the plot). Other useful commands for all data plots are the following: +\begin{itemize} + \item \DescribeEnv{dspClip} in order to make sure that all drawing commands are clipped to the bounding box defined by the box chart, you can enclose them individually in a predefined |dspClip| environment. See section~\ref{clipEx} for an example. + \item \DescribeMacro{dspPlotFrame} to redraw the framing box (useful to ``smooth out'' plots touching the frame) you can issue the command |\dspPlotFrame| + \item \DescribeMacro{dspCustomTicks} to draw arbitrarily placed ticks (and tick labels) on either axis, use + \begin{quote} + |\dspCustomTicks|\oarg{options}\marg{pos label pos label ...} + \end{quote} + where the axis is specified in the options field as either |axis=x| (default) or |axis=y| and where the argument is a list of space-separated coordinate-label pairs. If you use math mode for the labels, \emph{do not use spaces in your formulas} since that will confuse the list-parsing macros. + \item \DescribeMacro{dspText} place a text label anywhere in the plot using the axes coordinates: + \begin{quote} + |\dspText|(x, y)\marg{label} + \end{quote} +\end{itemize} + + +\subsection{Plotting Discrete-Time Signals} +The following commands generate stem (or ``lollipop'') plots; available options in the commands are all standards \psTricks options plus other specialized options when applicable: + +\begin{itemize} + \item \DescribeMacro{dspTaps} to plot a set of discrete time points use + \begin{quote} + |\dspTaps|\oarg{options}\marg{data} + \end{quote} + where \meta{data} is a list of space-separated index-value pairs (e.g., values pre-computed by an external numerical package). Allowed options are the generic \psTricks\ plot options. + + \item \DescribeMacro{dspTapsAt} to plot a set of discrete time points use + \begin{quote} + |\dspTapsAt|\oarg{options}\marg{start}\marg{data} + \end{quote} + where \meta{start} is the initial index value and \meta{data} is a list of space-separated signal values. Allowed options are the generic \psTricks\ plot options. + + \item \DescribeMacro{dspTapsFile} for large data sets, you can use + \begin{quote} + |\dspTapsFile|\oarg{options}\marg{fileName} + \end{quote} + where now \meta{fileName} points to an external text file of space-separated index-value pairs. + + \item \DescribeMacro{dspSignal} to plot a discrete-time signal defined in terms of PostScript primitives use + \begin{quote} + |\dspSignal|\oarg{options}\marg{PostScript code} + \end{quote} + The PostScript code must use the variable |x| as the independent variable; the |\dspPlot| environment sweeps |x| over all integers in the \meta{xmin}-\meta{xmax} interval defined for the plot; this can be changed for each individual signal by using the options \DescribeMacro{xmin,xmax} |xmin|=\meta{m} and/or |xmax|=\meta{n}. If you use \TeX\ macros in your PS code, make sure you include a space at the end of the macro definition. For instance, use |\def\gain\{0.75|\textvisiblespace|}|. + + \item \DescribeMacro{dspSignalOpt} to perform a PostScript initialization sequence before evaluating the signal, use + \begin{quote} + |\dspSignalOpt|\oarg{options}\marg{init}\marg{PostScript code} + \end{quote} + where \meta{init} is a valid PostScript sequence (e.g. {\tt \{/A [1 2 3] def\}} to initialize an array of data). +\end{itemize} + + +For example: +\vblock + \begin{dspPlot}{-3, 22}{-1.2, 1.2} + % for my postscript interpreter rand_max is 0x7FFFFFFF + \dspSignal[xmin=8]{rand 2147483647 div 0.5 sub 2 mul} + \dspTaps[linecolor=red]{3 1 4 1 5 1} + \dspTapsAt[linecolor=blue!60]{-2}{-.5 .5} + \end{dspPlot} +\end{Verbatim} +produces the following plot: + +\begin{centerfig} + \begin{dspPlot}{-3, 22}{-1.2, 1.2} + % for my postscript interpreter rand_max is 0x7FFFFFFF + \dspSignal[xmin=8]{rand 2147483647 div 0.5 sub 2 mul} + \dspTaps[linecolor=red]{3 1 4 1 5 1} + \dspTapsAt[linecolor=blue!60]{-2}{-.5 .5} + \end{dspPlot} +\end{centerfig} + +If you are viewing this document in a PostScript viewer, you can see that the random signal is different every time you reload the page, since the taps values are computed on the fly by the PostScript interpreter. + + +\subsection{Plotting Continuous-Time Signals} +Continuous-time functions can be plotted with the following commands: + +\begin{itemize} + \item \DescribeMacro{dspFunc} You can draw a continuous-time signal by using the command + \begin{quote} + |\dspFunc|\oarg{options}\marg{PostScript code} + \end{quote} + again, the PostScript code must use |x| as the independent variable; the range for |x| is the \meta{xmin}-\meta{xmax} interval and can be controlled for each signal independently via the|xmin| and |xmax| options. + + \item \DescribeMacro{dspFuncData} To plot a smooth function obtained by interpolating a list of space separated time-value pairs use + \begin{quote} + |\dspFuncData|\oarg{options}\marg{data} + \end{quote} + the interpolation is performed by the PostScript interpreter and can be controlled if necessary by using the appropriate \psTricks\ options. + + \item \DescribeMacro{dspFuncFile} For a continuous-time smooth interpolation of a pre-computed set of data points, use + \begin{quote} + |\dspFuncFile|\oarg{options}\marg{fileName} + \end{quote} + where \meta{fileName} points to a text file containing the data points as a space-separated list of abscissae and ordinates. + + \item \DescribeMacro{dspDiracs} To plot one or more Dirac deltas (symbolized by a vertical arrow) use + \begin{quote} + |\dspDiracs|\oarg{options}\marg{pos value pos value ...} + \end{quote} + where the argument is a list of space-separated time-value pairs. +\end{itemize} + +In the following example, note the use of the |dspClip| environment when plotting the hyperbola\footnote{Make sure not to leave any blank space in between the beginning and end of the |dspClip| environment, otherwise the axis labels may fall out of alignment.}:\label{clipEx} +\vblock +\begin{dspPlot}[yticks=1,sidegap=0]{0,10}{0,5} + \begin{dspClip}\dspFunc{1 3 x sub div abs}\end{dspClip} + \dspDiracs[linecolor=red]{3 4} +\end{dspPlot} +\end{Verbatim} + +\begin{centerfig} + \begin{dspPlot}[yticks=1,sidegap=0]{0,10}{0,5} + \begin{dspClip}\dspFunc{1 3 x sub div abs}\end{dspClip} + \dspDiracs[linecolor=red]{3 4} + \end{dspPlot} +\end{centerfig} + + + + +\subsection{Plotting Discrete- and Continuous-Time Signals Together} + +In the following examples we mix discrete- and continuous-time signals in the same plot: +\vblock +\begin{dspPlot}[xticks=10,yticks=0.2]{-5, 20}{-0.4, 1.2} + \def\sincx{x 0 eq {1} {x RadtoDeg sin x div} ifelse} + \dspSignal[xmax=10]{\sincx} + \dspFunc[linewidth=0.5pt,xmax=10]{\sincx} + \dspFunc[linestyle=dashed,linewidth=0.5pt,xmin=10]{\sincx} +\end{dspPlot} +\end{Verbatim} + +\begin{centerfig} + \begin{dspPlot}[xticks=10,yticks=0.2]{-5, 20}{-0.4, 1.2} + \def\sincx{x 0 eq {1} {x RadtoDeg sin x div} ifelse} + \dspSignal[xmax=10]{\sincx} + \dspFunc[linewidth=0.5pt,xmax=10]{\sincx} + \dspFunc[linestyle=dashed,linewidth=0.5pt,xmin=10]{\sincx} + \end{dspPlot} +\end{centerfig} + + +\vblock +\begin{dspPlot}[sidegap=0.5,yticks=none]{-6, 6}{-1.2, 1.2} + \def\signal{ 0.5235 mul RadtoDeg sin } + \def\quantize{ dup 0 gt {-0.5} {0.5} ifelse sub truncate } + \dspFunc[linecolor=gray,linewidth=2pt]{x \quantize \signal } + \dspFunc[linestyle=dotted,linewidth=1pt]{x \signal} + \dspSignal{x \signal} +\end{dspPlot} +\end{Verbatim} + +\begin{centerfig} + \begin{dspPlot}[sidegap=0.5,yticks=none]{-6, 6}{-1.2, 1.2} + \def\signal{ 0.5235 mul RadtoDeg sin } + \def\quantize{ dup 0 gt {-0.5} {0.5} ifelse sub truncate } + \dspFunc[linecolor=gray,linewidth=2pt]{x \quantize \signal } + \dspFunc[linestyle=dotted,linewidth=1pt]{x \signal} + \dspSignal{x \signal} + \end{dspPlot} +\end{centerfig} + + + +\subsection{Plotting Digital Spectra}\label{freqPlots} + +Digital frequency\footnote{By ``digital spectrum'' of a discrete-time sequence $x[n]$ we refer to the Discrete-Time Fourier transform +\[ + X(e^{j\omega}) = \sum_{n = -\infty}^{\infty} x[n] e^{-j\omega n} +\]} plots are set up by setting the option |xtype=freq| in the |dspPlot| environment; they are very similar to continuous-time plots, except for the following: + +\begin{itemize} + \item the horizontal axis represents angular frequency; its range is specified in normalized units so that, for instance, a range of {\tt \{-1,1\}} as the first argument to |dspPlot| indicates the frequency interval $[-\pi, \pi]$. + \item tick labels on the horizontal axis are expressed as integer fractions of $\pi$; in this sense, the |xticks| parameter, when set to a numeric value, indicates the denominator of said fractions. + \item |sidegap| is always zero in digital frequency plots. +\end{itemize} + +All digital spectra are $2\pi$-periodic, hence the $[-\pi, \pi]$ interval is sufficient to completely represent the function. However, if you want to explicitly plot the function over a wider interval, it is your responsibility to make the plotted data $2\pi$-periodic; the \DescribeMacro{dspPeriodize} |\dspPeriodize| macro can help you do that, as shown in the examples below. Also, when writing PostScript code, don't forget to scale the $x$ variable appropriately; in particular, PostScript functions of an angle use units in degrees, so you need to multiply |x| by 180 before computing trigonometric functions. + + + + +\vblock +\def\lambda{0.9 } +\def\magn{\lambda 1 sub dup mul 1 \lambda \lambda mul % + add x 180 mul cos 2 mul \lambda mul sub div } +\def\phase{\lambda x 180 mul sin mul -1 mul 1 \lambda % + x 180 mul cos mul sub atan 180 div 3.1415 mul } + +\begin{dspPlot}[xtype=freq,xticks=3,yticks=0.2, % + ylabel={Square magnitude $|H(e^{j\omega})|^2$}]{-1,1}{0,1.1} + \dspFunc{\magn } +\end{dspPlot} + +\begin{dspPlot}[xtype=freq,xticks=3,yticks=custom, % + ylabel={Phase (radians)}]{-1,1}{-1.57,1.57} + \dspFunc[xmax=0]{\phase } + \dspFunc[xmin=0]{-\phase -1 mul} + \dspCustomTicks[axis=y]{-1.57 $-\pi/2$ 0 0 1.57 $\pi/2$} +\end{dspPlot} +\end{Verbatim} +% + + + \def\lambda{0.9 } + \def\magn{\lambda 1 sub dup mul 1 \lambda \lambda mul % + add x 180 mul cos 2 mul \lambda mul sub div } + \def\phase{\lambda x 180 mul sin mul -1 mul 1 \lambda % + x 180 mul cos mul sub atan 180 div 3.1415 mul } + +\DeleteShortVerb{\|} +\begin{centerfig} + \begin{center} + \begin{dspPlot}[xtype=freq,xticks=3,yticks=0.2, % + ylabel={Square magnitude $|H(e^{j\omega})|^2$}]{-1,1}{0,1.1} + \dspFunc{\magn } + \end{dspPlot} + + \begin{dspPlot}[xtype=freq,xticks=3,yticks=custom,ylabel={Phase (radians)}]{-1,1}{-1.57,1.57} + \dspFunc[xmax=0]{\phase } + \dspFunc[xmin=0]{-\phase -1 mul} + \dspCustomTicks[axis=y]{-1.57 $-\pi/2$ 0 0 1.57 $\pi/2$} + \end{dspPlot} + \end{center} +\end{centerfig} +\MakeShortVerb{\|} + + + +\newpage + + +\vblock +\begin{dspPlot}[xtype=freq,xticks=1,yticks=1,xout=true]{0,1}{-0.5,1.5} + \psframe[fillstyle=vlines,% + hatchcolor=lightgray,hatchangle=20,% + linecolor=lightgray]% + (0,1.1)(0.4,0.9) + \psframe[fillstyle=vlines,% + hatchcolor=lightgray,hatchangle=20,% + linecolor=lightgray]% + (0.6,0.3)(1,-0.3) + \psline[linewidth=0.5pt](0.4,-.5)(0.4,1.5) + \psline[linewidth=0.5pt](0.6,-.5)(0.6,1.5) + \dspFunc[linecolor=red]{x 3.14 mul 0.5 mul 10 exp 1 add 1 exch div} + \dspPlotFrame + \dspCustomTicks{0.4 $0.4\pi$ 0.6 $0.6\pi$} +\end{dspPlot} +\end{Verbatim} + +\begin{centerfig} + \begin{dspPlot}[xtype=freq,xticks=1,yticks=1,,xout=true]{0, 1}{-0.5,1.5} + \psframe[fillstyle=vlines,% + hatchcolor=lightgray,hatchangle=20,% + linecolor=lightgray]% + (0,1.1)(0.4,0.9) + \psframe[fillstyle=vlines,% + hatchcolor=lightgray,hatchangle=20,% + linecolor=lightgray]% + (0.6,0.3)(1,-0.3) + \psline[linewidth=0.5pt](0.4,-.5)(0.4,1.5) + \psline[linewidth=0.5pt](0.6,-.5)(0.6,1.5) + \dspFunc[linecolor=red]{x 3.14 mul 0.5 mul 10 exp 1 add 1 exch div} + \dspPlotFrame + \dspCustomTicks{0.4 $0.4\pi$ 0.6 $0.6\pi$} + \end{dspPlot} +\end{centerfig} + + +The following example shows how to repeat an arbitrary spectral shape over more than one period. First let's define (and plot) a non-trivial spectral shape making sure that the free variable $x$ appears only at the beginning of the PostScript code: +\vblock +% triangular shape: +\def\triFun{abs 0.25 sub 1 0.25 sub div } +% parabolic shape: +\def\parFun{abs 0.25 div dup mul 1 exch sub } +% composite shape (cutoff at 0.5pi) +\def\comFun{ + dup dup dup dup % + -0.5 lt {pop pop pop pop 0} { % zero for x < -0.5 + 0.5 gt {pop pop pop 0 } { % zero for x > 0.5 + -0.25 lt {pop \triFun } { % triangle between + 0.25 gt {\triFun } % -.25 and -.5 + {\parFun} % else parabola + ifelse }% + ifelse }% + ifelse }% + ifelse } + +\begin{dspPlot}[xtype=freq,ylabel={$X(e^{j\omega})$}]{-1,1}{0,1.1} + \dspFunc{x \comFun } +\end{dspPlot} +\end{Verbatim} +% + + +% triangular shape: +\def\triFun{abs 0.25 sub 1 0.25 sub div } +% parabolic shape: +\def\parFun{abs 0.25 div dup mul 1 exch sub } +% composite shape (cutoff at 0.5pi) +\def\comFun{ + dup dup dup dup % + -0.5 lt {pop pop pop pop 0} { % zero for x < -0.5 + 0.5 gt {pop pop pop 0 } { % zero for x > 0.5 + -0.25 lt {pop \triFun } { % triangle between + 0.25 gt {\triFun } % -.25 and -.5 + {\parFun} % else parabola + ifelse }% + ifelse }% + ifelse }% + ifelse } +\begin{centerfig} + \begin{dspPlot}[xtype=freq,ylabel={$X(e^{j\omega})$}]{-1,1}{0,1.1} + \dspFunc{x \comFun } + \end{dspPlot} +\end{centerfig} + + +\DescribeMacro{dspPeriodize} Now we can periodize the function using the |\dspPeriodize| macro; plotting multiple periods becomes as simple as changing the axis range: +\vblock +\begin{dspPlot}[xtype=freq]{-2,2}{0,1.1} + \dspFunc{x \dspPeriodize \comFun } +\end{dspPlot} + +\begin{dspPlot}[xtype=freq,xticks=1]{-5,5}{0,1.1} + \dspFunc{x \dspPeriodize \comFun } +\end{dspPlot} +\end{Verbatim} + +\begin{centerfig} + \begin{dspPlot}[xtype=freq]{-2,2}{0,1.1} + \dspFunc{x \dspPeriodize \comFun } + \end{dspPlot} + + \begin{dspPlot}[xtype=freq,xticks=1]{-5,5}{0,1.1} + \dspFunc{x \dspPeriodize \comFun } + \end{dspPlot} +\end{centerfig} + + +%\end{document} + +\subsection{Plotting Analog Spectra} +To plot analog spectra, just set up a plot environment as you would to plot a continuous-time signal, then set the option |xticks=custom| and place your own frequency labels using |\dspCustomTicks| as in the example below: + +\vblock +\begin{dspPlot}[xtype=freq,xticks=custom,xlabel={freq. (Hz)},% + yticks=2,ylabel={$X(j\Omega)$}]{-10,10}{-1,5} + \dspFunc{x abs 4 gt {0} {x abs 2 div dup mul 4 exch sub} ifelse} + \dspCustomTicks{-4 $-\Omega_N$ 0 $0$ 4 $\Omega_N$ 8 $\Omega_s$} +\end{dspPlot} +\end{Verbatim} + +\begin{centerfig} + \begin{dspPlot}[xtype=freq,xticks=custom,xlabel={freq. (Hz)},% + yticks=2,ylabel={$X(j\Omega)$}]{-10,10}{-1.5,5} + \dspFunc{x abs 4 gt {0} {x abs 2 div dup mul 4 exch sub} ifelse} + \dspCustomTicks{-4 $-\Omega_N$ 0 $0$ 4 $\Omega_N$ 8 $\Omega_s$} + \end{dspPlot} +\end{centerfig} + + + +\subsection{Common Signal Shapes and Helper Functions} +To facilitate the creation of plots that commonly occur in signal processing theory, the package \dspf\ provides a PostScript implementation for the following set of functions; each macro acts on the free variable $x$ in a plot command (see examples below). + +\subsubsection*{Basic Shapes:} +\begin{itemize} + \item |\dspRect{a}{b}| computes a rectangular (box) function centered in $a$ and with support $2b$, i.e. $\mbox{rect}((x-a)/b)$ where + \[ + \mbox{rect}(x) = \left\{\begin{array}{ll} + 1 & \mbox{if $|x|<1/2$} \\ + 0 & \mbox{otherwise} + \end{array}\right. + \] + \item |\dspTri{a}{b}| computes a triangle function centered in $a$ and with support $2b$ + \item |\dspSinc{a}{b}| computes the scaled sinc function $\mbox{sinc}((x-a)/b)$, where + \[ + \mbox{sinc}(x) = \frac{\sin(\pi x)}{\pi x} + \] + \item |\dspQuad{a}{b}| computes a quadratic function (inverted parabola) centered in $a$ and with support $2b$ + \item |\dspExpDec{a}{b}| computes the decaying exponential response $b^(x-a)u[x-a]$ + \item |\dspPorkpie{a}{b}| computes a ``porkpie hat'' shape centered in $a$ and with support $2b$ + \item |\dspRaisedCos{a}{b}{r}| computes a raised cosine centered in $a$ with cutoff $b$ and rolloff $r$ +\end{itemize} + +\subsubsection*{Discrete Fourier Transform:} +\begin{itemize} + \item |\dspDFTMAG{x_0 x_1 ... x_{N-1}}| computes the magnitude of the Discrete Fourier transform (DFT) of the provided data points\footnote{Please note that the underlying implementation of the macro is not optimized; the computing time will be quadratic in the number of data points.}; the input value should be an integer. + \[ + X[k] = \vert \sum_{n=0}^{N-1}x[n]e^{j\frac{2\pi}{N}nk} \vert + \] + \item |\dspDFTRE{x_0 x_1 ... x_{N-1}}| computes the real part of the DFT + \item |\dspDFTIM{x_0 x_1 ... x_{N-1}}| computes the imaginary part of the DFT +\end{itemize} + + +\subsubsection*{Notable DTFTs:} +\begin{itemize} + \item |\dspSincS{a}{N}| computes the Discrete-Time Fourier transform (DTFT) of a zero-centered, symmetric $2N+1$-tap rectangular signal: + \[ + X(e^{j\omega}) = \frac{\sin(\omega(2N+1)/2)}{\sin(\omega/2)} + \] + The parameter $a$ can be used to shift the DTFT to the chosen center frequency. + \item |\dspSincC{a}{N}| computes the DTFT magnitude of a causal $N$-tap rectangular signal: + \[ + \vert X(e^{j\omega})\vert =\frac{\sin(\omega(N/2))}{\sin(\omega/2)} + \] + The parameter $a$ can be used to shift the DTFT to the chosen center frequency. +\end{itemize} + +\subsubsection*{Frequency Responses:} +\begin{itemize} + \item |\dspFIRI{a_0 a_1 ... a_{N-1}}| computes the (real-valued) frequency response of a zero centered $(2N+1)$-tap Type-I FIR filter with coefficients + \[ + a_{N-1}, a_{N-2}, \ldots, a_{1}, a_{0}, a_{1}, a_{2}, \ldots, a_{N-1}. + \] + The coefficient $a_0$ is the center tap and you need only specify the coefficients from $a_0$ to $a_{N-1}$. + + \item |\dspTFM{a_0 a_1 ... a_{N-1}}{b_1 b_2 ... b_{M-1}}| computes the magnitude response of a generic digital filter defined by the constant-coefficient difference equation: + \[ + y[n] = a_0 x[n] + ... + a_{N-1} x[n-N+1] - b_1 y[n-1] - ... - b_{M-1} y[n-M+1] + \] +\end{itemize} + +For instance: + +\vblock +\usepackage{dspFunctions} +... +\begin{dspPlot}[sidegap=1]{-2,10}{-1.2, 1.2} + \dspFunc{x \dspRect{-1}{1}} + \dspFunc{x \dspPorkpie{6}{2}} + \dspSignal[linecolor=gray]{x \dspSinc{2}{3} -1 mul} +\end{dspPlot} +\end{Verbatim} + +\begin{centerfig} + \begin{dspPlot}[sidegap=1]{-2,10}{-1.2, 1.2} + \dspFunc{x \dspRect{-1}{1}} + \dspFunc{x \dspPorkpie{6}{2}} + \dspSignal[linecolor=gray]{x \dspSinc{2}{3} -1 mul} + \end{dspPlot} +\end{centerfig} + + +We can generate a finite-length signal and plot its DFT magnitude as in this example, where the 32-point input signal is $\cos(2\pi/32 \cdot (27/5)n)$: + +\vblock +\begin{dspPlot}{0, 31}{0, 18} + \dspSignalOpt{/A [ 0 1 31 {360 32 div 5.4 mul mul cos} for ] def} + {x \dspDFTMAG{ A aload pop }} +\end{dspPlot} +\end{Verbatim} + +\begin{centerfig} + \begin{dspPlot}{0, 31}{0, 18} + \dspSignalOpt{/A [ 0 1 31 {360 32 div 5.4 mul mul cos} for ] def} + {x \dspDFTMAG{ A aload pop }} + \end{dspPlot} +\end{centerfig} + + + +The magnitude of simple FIR and IIR filter can be graphed easily like so: +\vblock +\begin{dspPlot}[xtype=freq,xout=true]{-1,1}{-0.5,1.5} + \dspFunc[linecolor=gray,linestyle=dashed]{x \dspSincS{0}{6} 13 div} + \dspFunc{x \dspFIRI{ 0.3501 0.2823 0.1252 -0.0215 -0.0876 + -0.0868 0.0374} } +\end{dspPlot} +\end{Verbatim} + +\begin{centerfig} + \begin{dspPlot}[xtype=freq,xout=true]{-1,1}{-0.5,1.5} + \dspFunc[linecolor=gray,linestyle=dashed]{x \dspSincS{0}{6} 13 div} + \dspFunc{x \dspFIRI{ 0.3501 0.2823 0.1252 -0.0215 -0.0876 -0.0868 0.0374} } +\end{dspPlot} +\end{centerfig} + +\vblock +\begin{dspPlot}[xtype=freq,xticks=4]{-1,1}{0,1.1} + % 8-th order Chebyshev filter example + % Coefficients from Matlab using [b a]=cheby1(8,0.5,0.25) + \dspFunc{x \dspTFM{0.000008952611389 0.000071620891113 + 0.000250673118897 0.000501346237795 0.000626682797244 + 0.000501346237795 0.000250673118897 0.000071620891113 + 0.000008952611389}{ 1.000000000000000 -5.975292291885454 + 16.581223292021008 -27.714232735429224 30.395097583553124 + -22.347296704268793 10.745098004349103 -3.089246336974975 + 0.407076858898017}} +\end{dspPlot} +\end{Verbatim} + +\begin{centerfig} + \begin{dspPlot}[xtype=freq,xticks=4]{-1,1}{0,1.1} + % 8-th order Chebyshev filter example + % Coefficients from Matlab using [b a]=cheby1(8,0.5,0.25) + \dspFunc{x \dspTFM{0.000008952611389 0.000071620891113 + 0.000250673118897 0.000501346237795 0.000626682797244 + 0.000501346237795 0.000250673118897 0.000071620891113 + 0.000008952611389}{ 1.000000000000000 -5.975292291885454 + 16.581223292021008 -27.714232735429224 30.395097583553124 + -22.347296704268793 10.745098004349103 -3.089246336974975 + 0.407076858898017}} + \end{dspPlot} +\end{centerfig} + + + +\section{Drawing Regions of Convergence, Poles and Zeros} + +\DescribeEnv{dspPZPlot} Pole-zero plots are defined by the environment +\begin{quote} + |\begin{dspPZPlot}|\oarg{options}\marg{M} \\ + ... \\ + |\end{dspPZPlot}| +\end{quote} +This plots a square section of the complex plane in which both axes span the $[-M, M]$ interval. Options for the plot are: + +\begin{optList} + \item[|width| = \meta{dim}]: width of the plot + \item[|height| = \meta{dim}]: height of the plot. Normally, since the range is the same for both the real and the imaginary axis, width and height should be equal. You can therefore specify just one of them and the other will be automatically set. If you explicitly specify both, you will be able to obtain an asymmetric figure. By default, width and height are equal to |\dspH|. +\end{optList} + +\begin{optList} + \item[|xticks| = |auto| $\mid$ |none| $\mid$ \meta{d}]: labeling of the real axis + \item[|yticks| = |auto| $\mid$ |none| $\mid$ \meta{d}]: labeling of the imaginary axis. When the option specifies a numeric value \meta{d}, that will be the spacing between two consecutive ticks on the axis. + \item[|cunits| = |true| $\mid$ |false|]: if true, labels the real and imaginary axis with ``Re'' and ``Im'' respectively. +\end{optList} + +\begin{optList} + \item[|circle| = \meta{r} ]: draws a circle centered in $z=0$ with radius $r$; by default $r=1$, so that the unit circle will be drawn; set to zero for no circle. + \item[|clabel| = \meta{label} ]: for a circle of radius $r$, places the selected label text at $z=r + j0$. By default the label is equal to the value of $r$. +\end{optList} + +\begin{optList} + \item[|roc| = \meta{r} ]: draws a {\em causal} region of convergence with radius $r$. + \item[|antiroc| = \meta{r} ]: draws an {\em anticausal} region of convergence with radius $r$. +\end{optList} + + + +\subsection{Poles and Zeros} +\DescribeMacro{dspPZ} To plot a pole or a zero at $z=a+jb$ use +\begin{quote} + |\dspPZ|\oarg{options}\marg{a, b} \\ +\end{quote} +which plots a pole by default; to plot a zero use the option |type=zero|. To associate a label to the point, use the option |label=|\meta{text}; if \meta{text} is |none| no label is printed; if \meta{text} is |auto| (which is the default) the point's coordinates are printed; otherwise the specified text is printed. Finally, you can specify the position of the label using the option |lpos=|\meta{angle}; by default, the angle's value is 45 degrees. + +\vblock +\begin{dspPZPlot}[clabel={$r_0$},roc=0.5]{1.5} + \dspPZPoint[label=none]{0.5,0.5} + \dspPZPoint[type=zero,label={$x[1]$},lpos=135]{0,1} + \dspPZPoint[type=zero,label={$x[0]$},lpos=90]{1.25, 0.78} +\end{dspPZPlot} +\end{Verbatim} + +\begin{centerfig} + \begin{dspPZPlot}[width=6cm,clabel={$r_0$},roc=0.5]{1.7} + \dspPZ[label=none]{0.5,0.5} + \dspPZ[type=zero,label={$x[1]$},lpos=135]{0,1} + \dspPZ[type=zero,label={$x[0]$},lpos=90]{1.25, 0.78} + \end{dspPZPlot} +\end{centerfig} + + + + +\section{Block Diagrams} +\DescribeEnv{dspBlocks} Block diagrams rely heavily on \psTricks ' |psmatrix| environment, for which ample documentation is available. To set up a block diagram use the environment +\begin{quote} + |\begin{dspBlocks}|\marg{x}\marg{y}\\ + ... \\ + |\end{dspBlocks}| +\end{quote} +where \meta{x} and \meta{y} define the horizontal and vertical spacing of the blocks in the diagram. Predefined functional blocks are listed in the table below and they can be used anywhere a node is required. Nodes are labeled in top-left matrix notation, i.e. the topmost leftmost node is at coordinates $(1,1)$ and indices increase rightward and downward. Connections between nodes can be drawn using \psTricks ' standard primitive |\ncline|; the package defines the following shorthands: +\begin{itemize} + \item \DescribeMacro{BDConnHNext} to connect with an arrow a node at $(n,m)$ to its neighboring node at $(n,m+1)$ use |\BDConnHNext|\marg{n}\marg{m} + \item \DescribeMacro{BDConnH} to connect with an arrow a node at $(n,m)$ to a node on the same row at $(n,p)$ use |\BDConnH|\oarg{options}\marg{n}\marg{m}\marg{p}\marg{label}, which uses \meta{options} as line options and \meta{label} as the label for the connection + \item \DescribeMacro{BDConnV} to connect with an arrow a node at $(n,m)$ to a node on the same column at $(q,m)$ use |\BDConnV|\oarg{options}\marg{n}\marg{m}\marg{q}\marg{label} +\end{itemize} + +\DeleteShortVerb{\|} +\MakeShortVerb{\#} + +\begin{center} +\begin{tabular}{|l|l|c|} +\hline +\bf function & \bf macro & \bf output \\ +\hline & & \\ +nodes & #\BDsplit# & \begin{dspBlocks}{1}{1}\BDsplit\end{dspBlocks} \\ +& & \\ + & #\BDadd# & \begin{dspBlocks}{1}{1}\BDadd\end{dspBlocks} \\ +& & \\ + & #\BDmul# & \begin{dspBlocks}{1}{1}\BDmul\end{dspBlocks} \\ +& & \\ \hline & & \\ +delays & #\BDdelay# & \begin{dspBlocks}{1}{1}\BDdelay\end{dspBlocks} \\ +& & \\ + & #\BDdelayN#\marg{N} & \begin{dspBlocks}{1}{1}\BDdelayN{N}\end{dspBlocks} \\ +& & \\ \hline & & \\ +filters & #\BDfilter#\marg{label} & \begin{dspBlocks}{1}{1}\BDfilter{$H(z)$}\end{dspBlocks} \\ +& & \\ + & #\BDfilterMulti#\marg{labels} & \begin{dspBlocks}{1}{1}\BDfilterMulti{multiple \\ lines}\end{dspBlocks} \\ + & {\footnotesize (use #\\# to separate lines)} & \\ +& & \\ + & #\BDlowpass# & \begin{dspBlocks}{1}{1}\BDlowpass[0.5em]\end{dspBlocks} \\ + & {\footnotesize (you can specify the size of the block, eg #\BDlowpass[2em]#)} & \\ +& & \\ \hline +\end{tabular} + +\begin{tabular}{|l|l|c|} +\hline +\bf function & \bf macro & \bf output \\ +\hline & & \\ +sampler & #\BDsampler# & \begin{dspBlocks}{1}{1}\BDsampler\end{dspBlocks} \\ +& & \\ + & #\BDsamplerFramed# & \begin{dspBlocks}{1}{1}\BDsamplerFramed[0.5em]\end{dspBlocks} \\ + & {\footnotesize (you can specify the size of the block, eg #\BDsamplerFramed[2em]#)} & \\ +& & \\ +interpolator & #\BDsinc# & \begin{dspBlocks}{1}{1}\BDsinc[0.5em]\end{dspBlocks} \\ + & {\footnotesize (you can specify the size of the block, eg #\BDsinc[2em]#)} & \\ +& & \\ \hline & & \\ +upsampler & #\BDupsmp#\marg{N} & \begin{dspBlocks}{1}{1}\BDupsmp{3}\end{dspBlocks} \\ +& & \\ +downsampler & #\BDdwsmp#\marg{N} & \begin{dspBlocks}{1}{1}\BDdwsmp{3}\end{dspBlocks} \\ +& & \\ \hline +\end{tabular} +\end{center} + + +\newpage + + +\vblock +\begin{dspBlocks}{.3}{1} +% first row: +$x[n]$ & & & \BDsplit & \BDdelay &% +\BDsplit & \BDdelay & \BDsplit & \BDdelay & \BDsplit & \hspace{3em} & % + & \BDdelay & \\ +% +% second row: + & & & & &% +\BDadd & & \BDadd & & \BDadd & \hspace{3em} & % + & & \BDadd & & $y[n]$ +% +% connections: + \ncline{1,1}{1,3} + \ncline{1,3}{1,5} + \ncline{1,5}{1,7} + \ncline{1,7}{1,9} + \ncline{1,9}{1,10} + \ncline[linestyle=dotted]{1,10}{1,12} + \ncline{1,12}{1,13} + \ncline{1,13}{1,14} + \ncline{2,10}{2,11} + \ncline[linestyle=dotted]{2,10}{2,13} + \ncline{1,4}{2,4}\tlput{$b_0$} + \BDConnH{2}{4}{6}{} + \BDConnV{1}{6}{2}{$b_1$} + \BDConnH{2}{6}{8}{} + \BDConnV{1}{8}{2}{$b_2$} + \BDConnH{2}{8}{10}{} + \BDConnV{1}{10}{2}{$b_3$} + \BDConnHNext{2}{13} + \BDConnV{1}{14}{2}{$b_{M-1}$} + \BDConnH{2}{14}{16}{} +\end{dspBlocks} +\end{Verbatim} + +\centerline{ +\begin{dspBlocks}{.3}{1} +\begin{dspBlocks}{.3}{1} +% first row: +$x[n]$ & & & \BDsplit & \BDdelay &% +\BDsplit & \BDdelay & \BDsplit & \BDdelay & \BDsplit & \hspace{3em} & % + & \BDdelay & \\ +% +% second row: + & & & & &% +\BDadd & & \BDadd & & \BDadd & \hspace{3em} & % + & & \BDadd & & $y[n]$ +% +% connections: + \ncline{1,1}{1,3} + \ncline{1,3}{1,5} + \ncline{1,5}{1,7} + \ncline{1,7}{1,9} + \ncline{1,9}{1,10} + \ncline[linestyle=dotted]{1,10}{1,12} + \ncline{1,12}{1,13} + \ncline{1,13}{1,14} + \ncline{2,10}{2,11} + \ncline[linestyle=dotted]{2,10}{2,13} + \ncline{1,4}{2,4}\tlput{$b_0$} + \BDConnH{2}{4}{6}{} + \BDConnV{1}{6}{2}{$b_1$} + \BDConnH{2}{6}{8}{} + \BDConnV{1}{8}{2}{$b_2$} + \BDConnH{2}{8}{10}{} + \BDConnV{1}{10}{2}{$b_3$} + \BDConnHNext{2}{13} + \BDConnV{1}{14}{2}{$b_{M-1}$} + \BDConnH{2}{14}{16}{} +\end{dspBlocks} +\end{dspBlocks} +} +\vspace{1em} + + +\vblock +\begin{dspBlocks}{2}{0.4} + $x(t)$~~ & \BDlowpass[0.8em] & \BDsamplerFramed[0.8em] & ~~$x[n]$ + \ncline{->}{1,1}{1,2} + \ncline{1,2}{1,3}^{$x_{LP}(t)$} + \ncline{->}{1,3}{1,4} +\end{dspBlocks} +\end{Verbatim} + + +\centerline{ +\begin{dspBlocks}{2}{0.4} + $x(t)$~~ & \BDlowpass[0.8em] & \BDsamplerFramed[0.8em] & ~~$x[n]$ + \ncline{->}{1,1}{1,2} + \ncline{1,2}{1,3}^{$x_{LP}(t)$} + \ncline{->}{1,3}{1,4} +\end{dspBlocks} +} +\vspace{3em} + +If you need to label nodes for complex connections, you may need to revert to the actual code for the node element, eg: + +\vblock +\begin{dspBlocks}{0.8}{0} + & & & [name=A1] \BDfilter{$H(z)$} & & $e^{-j\omega_c n}$ \\ + $\hat{s}(t)$~~ & \BDsampler + & [name=A,mnode=dot,linewidth=2pt] & + & [name=B,mnode=circle] + & \BDmul & [name=C] +% + \psset{arrows=->} + \ncangle[angleA=90,angleB=180,linewidth=\BDwidth]{A}{A1} + \ncangle[angleA=0,angleB=90,linewidth=\BDwidth]{A1}{B}^{~~~~$j$} + \ncbar[angleA=-90,angleB=-90,linewidth=\BDwidth]{A}{B} + \ncline{-}{2,1}{2,2} + \ncline{-}{2,2}{2,3}^{~~~~~~$\hat{s}[n]$} + \ncline{2,5}{2,6}^{$\hat{c}[n]$} + \ncline{-}{2,6}{2,7}^{~~~$\hat{b}[n]$} + \ncline{1,6}{2,6} +\end{dspBlocks} + +\vspace{7ex} + +\begin{dspBlocks}{1.2}{0} + [name=D,mnode=circle] $K \downarrow$ & \BDfilter{Slicer} & + \BDfilter{Descrambler} & + \hspace{1ex}\parbox{4ex}{\small \tt \bf ..01100\\ 01010...} + \psset{arrows=->} + \ncline{1,1}{1,2}^{$\hat{a}[n]$} + \ncline{1,2}{1,3} + \ncline{1,3}{1,4} +\end{dspBlocks} +\ncbarr[angleA=0,linewidth=1.2pt,linearc=0.2]{C}{D} +\end{Verbatim} + + +\begin{center} + \begin{dspBlocks}{0.8}{0} + & & & [name=A1] \BDfilter{$H(z)$} & & $e^{-j\omega_c n}$ \\ + $\hat{s}(t)$~~ & \BDsampler + & [name=A,mnode=dot,linewidth=2pt] & + & [name=B,mnode=circle] + & \BDmul & [name=C] +% + \psset{arrows=->} + \ncangle[angleA=90,angleB=180,linewidth=\BDwidth]{A}{A1} + \ncangle[angleA=0,angleB=90,linewidth=\BDwidth]{A1}{B}^{~~~~$j$} + \ncbar[angleA=-90,angleB=-90,linewidth=\BDwidth]{A}{B} + \ncline{-}{2,1}{2,2} + \ncline{-}{2,2}{2,3}^{~~~~~~$\hat{s}[n]$} + \ncline{2,5}{2,6}^{$\hat{c}[n]$} + \ncline{-}{2,6}{2,7}^{~~~$\hat{b}[n]$} + \ncline{1,6}{2,6} + \end{dspBlocks} + + \vspace{7ex} + + \begin{dspBlocks}{1.2}{0} + [name=D,mnode=circle] $K \downarrow$ & \BDfilter{Slicer} & + \BDfilter{Descrambler} & \hspace{1ex}\parbox{4ex}{\small \tt \bf ..01100\\ 01010...} + \psset{arrows=->} + \ncline{1,1}{1,2}^{$\hat{a}[n]$} + \ncline{1,2}{1,3} + \ncline{1,3}{1,4} + \end{dspBlocks} + \ncbarr[angleA=0,linewidth=1.2pt,linearc=0.2]{C}{D} +\end{center} + +\newpage + +\begin{thebibliography}{1} + + \bibitem{TVZ93} Timothy Van Zandt, {\em PSTricks - PostScript macros for generic TEX}, \url{http://www.tug.org/application/PSTricks}, 1993. + + \bibitem{HV} PSTricks Web pages, maintened by Herbert Vo{\ss}. \url{http://www.pstricks.de} + + \bibitem{ps} Adobe Systems Incorporated, {\em PostScript Language Reference Manual}, Addison-Wesley, 3 edition, 1999. + + \bibitem{BC} Bill Casselman {\em Mathematical Illustrations}, Cambridge University Press, 2005. + + \bibitem{fp} Michael Mehlich, {\em ``fp'': Fixed point arithmetic for TEX}, \url{CTAN:macros/latex/contrib/fp}. + + \bibitem{PV} Paolo Prandoni and Martin Vetterli, {\em Signal Processing for Communications}, 2008, \url{http://www.sp4comm.org} + +\end{thebibliography} + + +\end{document} diff --git a/Master/texmf-dist/tex/latex/dsptricks/dspblocks.sty b/Master/texmf-dist/tex/latex/dsptricks/dspblocks.sty new file mode 100644 index 00000000000..b7aba995a9e --- /dev/null +++ b/Master/texmf-dist/tex/latex/dsptricks/dspblocks.sty @@ -0,0 +1,116 @@ +%% This is the package dspblocks +%% +%% (c) Paolo Prandoni +%% +%% This program can be redistributed and/or modified under the terms +%% of the LaTeX Project Public License Distributed from CTAN archives +%% in directory macros/latex/base/lppl.txt. +%% +%% DESCRIPTION: +%% `dspblocks' is a companion package to dsptricks; it contains a +%% set of macros to draw the types of block diagrams commonly +%% used in DSP theory +%% +%% v1.0, July 2014 +%% + +% required packages: +\RequirePackage{calc} +\RequirePackage{fp} +\RequirePackage{pst-xkey} +\RequirePackage{fmtcount} +\RequirePackage{ifthen} +% +\ProvidesPackage{dspblocks}[2014/07/24 package for signal processing graphics] + + +% turn off FP messages +\FPmessagesfalse + +\makeatletter + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%% Set up BLOCK DIAGRAM plot +% +% \begin{psdrawBDmatrix}[OPTIONS]{X_SPACING}{Y_SPACING} +% +% X_SPACING +% Y_SPACING vertical and horizontal spacing +% +% Once in Block diagram mode the following commands are available +% (they all create nodes) +% +% \BDadd adder +% \BDmul multiplier +% \BDdelay z^{-1} delay block +% \BDdelayN{N} z^{-N} delay block +% \BDfilter{text} filter box +% \BDfilterMulti{text} multiline filter box +% \BDsplit splitting point (dot) +% \BDupsmp{K} upsampler by K +% \BDdwsmp{K} downsampler by K +% + +\def\BDwidth{1.2pt} +\psset{xunit=1mm,yunit=1mm,linewidth=\BDwidth} +\def\BDadd{[mnode=circle] +}% +\def\BDsub{[mnode=circle] -}% +\def\BDmul{[mnode=circle] $\times$}% +\def\BDdelay{\psframebox[framesep=.3]{$z^{-1}$}}% +\def\BDdelayN#1{\psframebox[framesep=.3]{$z^{-#1}$}}% +\def\BDfilter#1{\psframebox[framesep=.3]{#1}}% +\def\BDfilterMulti#1{\psframebox% + {\begin{tabular}{c} #1 \end{tabular}}}% +\def\BDsplit{[mnode=dot,linewidth=1.5pt]}% +\def\BDupsmp#1{[mnode=circle] $#1 \uparrow$}% +\def\BDdwsmp#1{[mnode=circle] $#1 \downarrow$}% +\def\BDsampler{\raisebox{-14.6pt}{ + \psset{xunit=1em,yunit=1em,linewidth=1.2pt}% + \pspicture(-2.6,-1.8)(1,1.8)% + \psline(-3,0)(-1.6,0)(0.7,1.2) + \psline(0.8,0)(1,0) + \psarc[linewidth=1pt]{<-}(-1.2,0){1.4em}{-10}{55} + \endpspicture}} +\newcommand{\BDsamplerFramed}[1][1em]{ + \newskip\tmpLen \tmpLen=#1% + \raisebox{-1.5\tmpLen}{% + \psframebox[linewidth=1.2pt]{% + \psset{unit=#1,linearc=0}% + \pspicture(-3.1,-2)(3,2)% + \psline(-2.8,-0.2)(-1.6,-0.2)(1.2,1.4)% + \psline(1.1,-0.2)(1.8,-0.2)% + \psarc[linewidth=1pt]{<-}(-1.6,0){2}{-10}{55}% + \endpspicture}}} +\newcommand{\BDlowpass}[1][1em]{% + \newskip\tmpLen \tmpLen=#1% + \raisebox{-1.5\tmpLen}{% + \psframebox[linewidth=1.2pt]{% + \psset{unit=#1,linearc=0}% + \pspicture(-3.1,-2)(3,2)% + \psline{->}(-2.8,-1)(2.8,-1)% + \psline{->}(0,-1.8)(0,2)% + \psline[linewidth=1.5pt](-1,-1)(-1,0.8)(1,0.8)(1,-1)% + \endpspicture}}} +\newcommand{\BDsinc}[1][1em]{% + \newskip\tmpLen \tmpLen=#1% + \raisebox{-1.5\tmpLen}{% + \psframebox[linewidth=1.2pt]{% + \psset{unit=#1,linearc=0}% + \pspicture(-3.1,-2)(3,2)% + \psline{->}(-2.8,-.5)(2.8,-.5)% + \psline{->}(0,-1.8)(0,2)% + \psplot[linewidth=1pt, plotpoints=500,linejoin=1]{-2.5}{2.5}{x \dspSinc{0}{0.5} 1.5 mul .5 sub}% + \endpspicture}}} + +\newenvironment{dspBlocks}[2]{% + \begin{psmatrix}[colsep=#1,rowsep=#2,emnode=R] }{% + \end{psmatrix} +} + +\newcommand{\BDConnH}[5][]{\ncline[#1]{->}{#2,#3}{#2,#4}\taput{#5}} +\newcommand{\BDConnHNext}[2]{\FPupn\n{#2 1 add 0 trunc}\ncline{->}{#1,#2}{#1,\n}} +\newcommand{\BDConnV}[5][]{\ncline[#1]{->}{#2,#3}{#4,#3}\tlput{#5}} + +\makeatother \ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/dsptricks/dspfunctions.sty b/Master/texmf-dist/tex/latex/dsptricks/dspfunctions.sty new file mode 100644 index 00000000000..ae63eccaa0d --- /dev/null +++ b/Master/texmf-dist/tex/latex/dsptricks/dspfunctions.sty @@ -0,0 +1,258 @@ +%% This is the package dspfunctions +%% +%% (c) Paolo Prandoni +%% +%% This program can be redistributed and/or modified under the terms +%% of the LaTeX Project Public License Distributed from CTAN archives +%% in directory macros/latex/base/lppl.txt. +%% +%% DESCRIPTION: +%% `dspfunctions' is a companion package to dsptricks; it contains a +%% set of postscript macros to compute the value of various DSP +%% common functions +%% +%% v1.0, July 2014 +%% + +\ProvidesPackage{dspfunctions}[2014/07/24 package for signal processing graphics] + +\def\dspToDeg{180 mul } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspRect{a}{b} rect((x-a)/b) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspRect#1#2{ #1 sub abs #2 div 0.5 gt {0} {1} ifelse } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspTri{a}{b} triangle((x-a)/b) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspTri#1#2{ #1 sub abs #2 div dup 1 gt {pop 0} {1 exch sub} ifelse } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspExpDec{a}{b} b^(x-a)u[x-a] +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspExpDec#1#2{ #1 sub dup 0 lt {pop 0} {#2 exch exp} ifelse } + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspQuad{a}{b} quadratic((x-a)/b) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspQuad#1#2{ #1 sub abs #2 div dup 1 gt {pop 0} {dup mul 1 exch sub } ifelse } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Porkpie hat shape (useful for spectral prototypes +% \dspPorkpie{a}{b} phi((x-a)/b) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspPorkpie#1#2{ #1 sub #2 div dup abs 1 gt {pop 0}% + {32.4 mul dup cos exch % + dup 3 mul cos 2 mul exch % + 12 mul cos -0.7 mul % + add add 0.31 mul 0.017 add } ifelse } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Raised cosine +% \dspRaisedCos{cutoff}{rolloff} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspRaisedCos#1#2{abs % + dup dup + 1 #2 sub #1 mul lt % + {pop pop 1} % + {1 #2 add #1 mul gt % + {pop 0} {1 #2 sub #1 mul sub 2 #2 #1 mul mul div 3.14 mul RadtoDeg cos 1 add 0.5 mul} ifelse } % + ifelse } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Raised cosine, better syntax +% \dspRaisedCos{a}{b}{r} b = cutoff, r = rolloff +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspRaisedCosine#1#2#3{% + #1 sub abs #2 div + dup dup + 1 #3 sub lt + {pop pop 1} + {1 #3 add gt + {pop 0} + {1 #3 sub sub 2 #3 mul div 180 mul cos 1 add 0.5 mul} + ifelse} + ifelse } + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspSinc{a}{b} sinc((x-a)/b) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspSinc#1#2{ #1 sub #2 div dup 0 eq {pop 1} {dup 180 mul sin exch 3.1415 mul div} ifelse } + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspSincN{a}{b} (1/b)sinc((x-a)/b) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspSincN#1#2{\dspSinc{#1}{#2} #2 div } + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Fourier transform of a symmetric 2N+1 tap rect +% \dspSincS{a}{N} sin((x-a)(2N+1)/2)/sin((x-a)/2) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspSincS#1#2{ #1 sub 90 mul dup #2 2 mul 1 add mul sin exch sin dup 0 eq {pop pop #2 2 mul 1 add} {div} ifelse} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Fourier transform magnitude of a causal N tap rect +% (phase is e^{-j\frac{N-1}{2}\omega}) +% \dspSincC{a}{N} sin((x-a)(N/2))/sin((x-a)/2) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspSincC#1#2{ #1 sub 90 mul dup #2 mul sin exch sin dup 0 eq {pop pop #2} {div} ifelse} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% \dspRand % Random number uniformly distributed over [-1 1] +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspRand{rand 2147483647 div 0.5 sub 2 mul } + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Discrete Fourier Transform of an input sequence; input is +% the integer value of the DFT coefficient. +% +% \dspDFTRE{a_0 a_1 ... a_{N-1}} (real part) +% \dspDFTIM{a_0 a_1 ... a_{N-1}} (imaginary part) +% \dspDFTMAG{a_0 a_1 ... a_{N-1}} (magnitude) +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspDFT#1{% + cvi [#1] length mod % DFT is N periodic + 360 mul [#1] length div % w = (2k\pi)/N + 0 % index n + 0 % accumulator Re + 0 % accumulator Im + [#1] % data points + { % STACK: + % w n re im a_n + dup % w n re im a_n a_n + 5 index % w n re im a_n a_n w + 5 index % w n re im a_n a_n w n + mul dup % w n re im a_n a_n nw nw + sin exch cos % w n re im a_n a_n sin(nw) cos(nw) + 4 1 roll mul % w n re im cos(nw) a_n (a_n)sin(nw) + 3 1 roll mul % w n re im (a_n)sin(nw) (a_n)cos(nw) + 4 1 roll add % w n (a_n)cos(nw) re im' + 3 1 roll add exch % w n re' im' + 3 2 roll 1 add % w re' im' n' + 3 1 roll % w n re im + } forall + 4 2 roll pop pop % re im +} +\def\dspDFTRE#1{\dspDFT{#1} pop } +\def\dspDFTIM#1{\dspDFT{#1} exch pop } +\def\dspDFTMAG#1{\dspDFT{#1} dup mul exch dup mul add sqrt } + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Frequency response of a (2N+1)-tap Type-I FIR computed at a given +% normalized frequency value. Frequency response is real for Type-I +% The filter is considered zero-centered, so a_0 is the center tap +% +% \dspFIRI{a_0 a_1 ... a_{N-1}} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspFIRI#1{% + \dspToDeg % input to degrees + 0 % index n + 0 % accumulator A + [#1] % coefficients a_n + { + 3 index % x + 3 index % n [*** using index INCREASES stack size... so it's 3 3 rather than 3 2] + mul cos mul % a_n cos nx + add % accumulate + exch 1 add exch % i++ + } forall + 3 1 roll pop pop + 2 mul % final value is 2A - a_0 + [#1] 0 get sub +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% Magnitude response of a generic digital filter defined by the +% constant-coefficient difference equation: +% y[n] = a_0 x[n] + a_1 x[n-1] + ... + a_{N-1} x[n-N+1] +% - b_1 y[n-1] - ... - b_{M-1} y[n-M+1] +% +% The response is computed at the given normalized frequency value +% +% \dspTFM{a_0 a_1 ... a_{N-1}}{b_1 b_2 ... b_{M-1}} +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\dspTFM#1#2{% + \dspToDeg % input to degrees + dup % save a copy for denominator + 0 % index n + 0 % accumulator Re + 0 % accumulator Im + [#1] % coefficients a_n + { % STACK (neglecting saved input at bottom): + % x n re im a_n + dup % x n re im a_n a_n + 5 index % x n re im a_n a_n x + 5 index % x n re im a_n a_n x n + mul dup % x n re im a_n a_n nx nx + sin exch cos % x n re im a_n a_n sin(nx) cos(nx) + 4 1 roll mul % x n re im cos(nx) a_n (a_n)sin(nx) + 3 1 roll mul % x n re im (a_n)sin(nx) (a_n)cos(nx) + 4 1 roll add % x n (a_n)cos(nx) re im' + 3 1 roll add exch % x n re' im' + 3 2 roll 1 add % x re' im' n' + 3 1 roll % x n re im + } forall + 4 2 roll pop pop % re im + dup mul exch dup mul add % (re^2 + im^2) + sqrt % mag of the numerator of transfer function + exch % bring up saved input copy + 0 % same loop for the b_n coefficients + 0 + 0 + [#2] + { + dup + 5 index + 5 index + mul dup + sin exch cos + 4 1 roll mul + 3 1 roll mul + 4 1 roll add + 3 1 roll add exch + 3 2 roll 1 add + 3 1 roll + } forall + 4 2 roll pop pop + dup mul exch dup mul add + sqrt + div %0 eq {pop pop 0} {div} ifelse +} + diff --git a/Master/texmf-dist/tex/latex/dsptricks/dsptricks.sty b/Master/texmf-dist/tex/latex/dsptricks/dsptricks.sty new file mode 100644 index 00000000000..5b075c043c1 --- /dev/null +++ b/Master/texmf-dist/tex/latex/dsptricks/dsptricks.sty @@ -0,0 +1,1071 @@ +%% This is the package dsptricks +%% +%% (c) Paolo Prandoni +%% +%% This program can be redistributed and/or modified under the terms +%% of the LaTeX Project Public License Distributed from CTAN archives +%% in directory macros/latex/base/lppl.txt. +%% +%% DESCRIPTION: +%% `dsptricks' is a LaTeX package based on PSTricks to plot discrete- and continuous-time +%% signals, pole-zero plots and DSP block diagrams. The package has been developed +%% while writing the textbook "Signal Processing for Communication" by P. Prandoni +%% and M. Vetterli, freely available at www.sp4comm.org +%% +%% v1.0, July 2014 +%% +\RequirePackage{pstricks} +\RequirePackage{pstricks-add} +\RequirePackage{pst-xkey} +\RequirePackage{calc} +\RequirePackage{fp} +\RequirePackage{ifthen} +% +\ProvidesPackage{dsptricks}[2014/07/24 package for signal processing graphics] + +% turn off FP messages +\FPmessagesfalse + +\makeatletter + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Sizes and units: +%% +%% default values for plot size +%% +\newlength{\dspWidth}\setlength{\dspWidth}{0.7\textwidth} +\newlength{\dspHeight}\setlength{\dspHeight}{0.43\dspWidth} +\def\dspAxisColor{black} +% +%% Actual size (this is the size of the chart's frame, labels are extra) +\newlength{\dspW} +\newlength{\dspH} +%% Basic Unit is a function of plot size +\newlength{\dspBU} +%% Derived units: +\newlength{\dspLineWidth} +\newlength{\dspStemWidth} +\newlength{\dspDotSize} +\newlength{\dspTickLen} +\newlength{\dspXTickGap} +\newlength{\dspYTickGap} +\newlength{\dspTickLineWidth} +\newlength{\dspFrameLineWidth} +%% psTricks units +\newlength{\dspUnitX} +\newlength{\dspUnitY} +\newlength{\dspTmpLen} +%% booleans +\newif\ifXTicks +\newif\ifDoXTicks +\newif\ifYTicks +\newif\ifDoYTicks +\newif\ifXLabel +\newif\ifYLabel +\newif\ifXAxisExp +\newif\ifYAxisExp +\newif\ifXAxisFreq +\newif\ifXInside + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% dspPlot environment: +%% +%% \begin{dspPlot}[OPTIONS]{xMin, xMax}{yMin, yMAx} +%% +%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Keys for data plots : +%% +\define@key{dspDP}{width}{\setlength{\dspW}{#1}} +\define@key{dspDP}{height}{\setlength{\dspH}{#1}} +\define@key{dspDP}{xlabel}{\def\dspXLabel{#1}\XLabeltrue} +\define@key{dspDP}{ylabel}{\def\dspYLabel{#1}\YLabeltrue} +\define@key{dspDP}{rlabel}{\def\dspYLabelR{#1}\YLabeltrue} % right-side y-axis label +\define@key{dspDP}{sidegap}{\def\sg{#1}} +\define@choicekey*+{dspDP}{xtype}[\ll\ln]{time,freq}[time]{% + \ifcase\ln\relax + \XAxisFreqfalse + \or + \XAxisFreqtrue + \fi}{} +\define@choicekey*+{dspDP}{xticks}[\ll\ln]{auto,none,custom}[auto]{% + \DoXTickstrue\XTickstrue\def\incX{-1}\def\piFrac{2} + \ifcase\ln\relax + \relax + \or + \DoXTicksfalse\XTicksfalse + \or + \DoXTicksfalse + \fi}{% + \DoXTickstrue\XTickstrue + \def\incX{#1}\def\piFrac{#1}} +\define@choicekey*+{dspDP}{yticks}[\ll\ln]{auto,none,custom}[auto]{% + \DoYTickstrue\YTickstrue\def\incY{-1} + \ifcase\ln\relax + \relax + \or + \DoYTicksfalse\YTicksfalse + \or + \DoYTicksfalse + \fi}{% + \DoYTickstrue\YTickstrue + \def\incY{#1}} +\newif\ifXTicksOut +\define@key{dspDP}{xout}{\XTicksOuttrue} +\define@key{dspDP}{inticks}{\XInsidetrue} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% dspPlot environment +%% +\newenvironment{dspPlot}[3][]{% +% default values + \def\dspXlabel{}\XLabelfalse% + \def\dspYLabel{}\def\dspYLabelR{}\YLabelfalse% + \XAxisFreqfalse% + \XTicksOutfalse% + \setlength{\dspW}{\dspWidth}\setlength{\dspH}{\dspHeight}% + + \presetkeys{dspDP}{xticks=auto,yticks=auto}{}% + \presetkeys{dspDP}{sidegap=-1}{}% + \setkeys{dspDP}{#1}% +%% +%% set up + \ifXAxisFreq\def\sg{0} \fi% + \dspSetDims#2,#3,\sg\relax% + \dspSetupAxes +%% +%% special x-axis for frequency plots + \ifXAxisFreq\FPset\incX{1}% + \ifXAxisExp% + % x-axis is not on bottom; skip last values + \FPupn\stX{\dspMinX{} \piFrac{} * 1 + 0 trunc}% + \FPupn\tlimX{\stX{} \dspMaxX{} \piFrac{} * - 0 trunc}% + \else% + \FPupn\stX{\dspMinX{} \piFrac{} * 0 trunc}% + \FPupn\tlimX{\stX{} \dspMaxX{} \piFrac{} * - 1 + 0 trunc}\relax\fi% + % + \ifXTicksOut% undo above if ticks explicitly out + \FPupn\stX{\dspMinX{} \piFrac{} * 0 trunc}% + \FPupn\tlimX{\stX{} \dspMaxX{} \piFrac{} * - 1 + 0 trunc}\relax\fi + % + \def\thisTickX##1{% + \FPupn\u{\piFrac{} ##1 /}% + \psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](\u,\haY)(\u,\tickEndX)} + \def\thisTickLabelX##1##2{% + \FPupn\u{\piFrac{} ##1 /}% + \rput*[B]{{0}}(\u,\tickTxtX){{\simplifyPiFrac{##1}{\piFrac}}}}% + \else + \def\thisTickX{\dspTickX}\def\thisTickLabelX{\dspTickLabelX}\relax\fi +%% +%% start the plot + \begin{pspicture}(\LX,\BY)(\RX,\TY) + %\showpointstrue + %\psframe[dimen=middle,linewidth=1pt,linecolor=red](\LX,\BY)(\RX,\TY)% + \ifXAxisExp\psline[linewidth=\dspFrameLineWidth,linecolor=\dspAxisColor](\dspMinX,0)(\dspMaxX,0)\fi + \dspPlotFrame +%% +%% draw ticks selectively according to user options + \ifDoXTicks\multido{\n=\stX+\incX}{\tlimX}{\thisTickX{\n}}\fi + \ifDoYTicks\multido{\n=\stY+\incY}{\tlimY}{\dspTickY{\n}}\fi +}{% +%% tick labels + \psset{xunit=\dspUnitX,yunit=\dspUnitY} %user may have changed those + \ifDoXTicks\multido{\n=\stX+\incX}{\tlimX}{\thisTickLabelX{\n}{$\n$}}\fi + \ifDoYTicks\multido{\n=\stY+\incY}{\tlimY}{\dspTickLabelY{\n}{$\n$}}\fi + \dspLabels +\end{pspicture}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Custom ticks +%% +%% \dspCustomTicks[axis={x|y}]{value label ...} +%% +%% if using macros for values, enclose them in curly braces: +%% \def\a{1 } +%% \dspCustomTicks{{\a} 1} +%% +\define@choicekey*{dspCT}{axis}[\ll\ln]{x,y,ry}[x]{% + \def\dspCA{\ln}} +\define@key{dspCT}{color}{\def\tickColor{#1}} +\newcommand{\dspCustomTicks}[2][]{% + \presetkeys{dspCT}{axis=x,color=black}{}% + \setkeys{dspCT}{#1}% + \ifcase\dspCA\relax% + \def\dspMkTk##1##2{\dspTickX{##1}{\dspTickLabelX{##1}{##2}}}% + \or + \def\dspMkTk##1##2{\dspTickY{##1}{\dspTickLabelY{##1}{##2}}}% + \or + \def\dspMkTk##1##2{{\dspTickLabelYR{##1}{##2}}}% + \fi + \def\dspMakeTicks##1 ##2 ##3\relax{% + \ifx&##3& + \dspMkTk{##1}{##2} % + \else + \dspMkTk{##1}{##2} \relax % + \dspMakeTicks##3\relax% + \fi}% + \dspMakeTicks#2 \relax} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Draw legend +%% +%% \dspLegend(x,y){color label color label ...} +%% +\def\dspLegend(#1,#2)#3{% + \rput[lt](#1,#2){\fbox{% + \begin{tabular}{ll} + \@dsplegend#3 \@empty + \end{tabular}}}} +\def\@dsplegend#1 #2 #3{% + {\color{#1}\rule[0.5ex]{2em}{2pt}} & #2\\ \space % fbox here to have a visual test + \ifx #3\@empty\else + \expandafter\@dsplegend + \fi + #3} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Redraw frame around plot +%% +\newcommand{\dspPlotFrame}{ + \psframe[dimen=middle,linewidth=\dspFrameLineWidth,linecolor=black]% + (\dspMinX,\dspMinY)(\dspMaxX,\dspMaxY)} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Environment to clip plots to within the frame box. Do not leave +%% spaces in the environment's body otherwise graph will shift +%% +\newenvironment{dspClip}{% + \psclip{\psframe[dimen=middle,linestyle=none](\dspMinX,\dspMinY)(\dspMaxX,\dspMaxY)}}{% + \endpsclip} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plotting discrete-time signals in the dspPlot environment: +%% +%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Keys for plotting functions (these are set together with pstricks keys +%% so they must use the [psset] prefix and be declared) +%% +%% xmin=N, +%% xmax=N range for the plotted signal +%% +\define@key[psset]{dspData}{xmin}{\def\dspXmin{#1}} +\define@key[psset]{dspData}{xmax}{\def\dspXmax{#1}} +\pst@addfams{dspData} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plot discrete-time points +%% +%% \dspTaps[OPTIONS]{x1 y1 x2 y2 ...} +%% +\newcommand{\dspTaps}[2][]{% + \listplot[plotstyle=LineToXAxis, linestyle=solid,% + showpoints=true, dotstyle=*, linewidth=\dspStemWidth,% + dotsize=\dspDotSize, #1]{\expandafter\m@keList#2 \relax}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plot discrete-time points starting at a given abscissa +%% Data in this case is only ordinates +%% +%% \dspTapsAt{x0}{y0 y1 y2,...} +%% +\newcommand{\dspTapsAt}[3][]{% + % use postscript to iterate over space-separated list and create indices + \listplot[plotstyle=LineToXAxis, linestyle=solid,% + showpoints=true, dotstyle=*, linewidth=\dspStemWidth,% + dotsize=\dspDotSize, #1]{% + #2 + [#3] { % n [] + % n a0 + 1 index % n a0 n + 1 add + } forall + pop +}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plot discrete-time signal from a data file +%% +%% \dspTapsFile[OPTIONS]{FILE} +%% +\newcommand{\dspTapsFile}[2][]{% + \readdata{\data}{#2}% + \listplot[plotstyle=LineToXAxis, linestyle=solid,% + showpoints=true, dotstyle=*,% + linewidth=\dspStemWidth, dotsize=\dspDotSize,% + #1]{\data}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plot discrete-time signal +%% +%% \dspSignal[OPTIONS]{PS code} +%% +\newcommand{\dspSignal}[2][]{% + \presetkeys[psset]{dspData}{xmin=\dspMinActX, xmax=\dspMaxActX}{}% + \setkeys*[psset]{dspData}{#1}% + \FPupn\mn{{\dspXmin} 0 trunc clip }% + \FPupn\mx{{\dspXmax} 0 trunc clip }% + \FPupn\ntaps{\mn{} \mx{} - 1 + 0 trunc clip}% + \psplot[plotstyle=LineToXAxis, linestyle=solid,% + showpoints=true, dotstyle=*,% + linewidth=\dspStemWidth, dotsize=\dspDotSize,% + plotpoints=\ntaps, #1]% + {\mn}{\mx}{#2}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plot discrete-time signal with postscript initialization options +%% +%\dspSignalOpt[OPTIONS]{PS init code}{PS code} +%% +\newcommand{\dspSignalOpt}[3][]{% + \presetkeys[psset]{dspData}{xmin=\dspMinActX, xmax=\dspMaxActX}{}% + \setkeys*[psset]{dspData}{#1}% + \FPupn\ntaps{\dspXmin{} \dspXmax{} - 1 + 0 trunc}% + \psplot[plotstyle=LineToXAxis, linestyle=solid,% + showpoints=true, dotstyle=*,% + linewidth=\dspStemWidth, dotsize=\dspDotSize,% + plotpoints=\ntaps, #1]% + {\dspXmin}{\dspXmax}[{#2}]{#3}} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plotting continuous-time signals in the dspPlot environment: +%% +%% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plot smooth function +%% +%% \dspFunc[OPTIONS]{PS code} +%% +\newcommand{\dspFunc}[2][]{% + \presetkeys[psset]{dspData}{xmin=\dspMinActX, xmax=\dspMaxActX}{}% + \setkeys*[psset]{dspData}{#1}% + \psplot[linewidth=\dspLineWidth, plotpoints=\dspPSPoints,% + linejoin=1,#1]{\dspXmin}{\dspXmax}{#2}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plot smooth function with postscript initialization options +%% +%% \dspFuncOpt[OPTIONS]{PS init code}{PS code} +%% +\newcommand{\dspFuncOpt}[3][]{% + \presetkeys[psset]{dspData}{xmin=\dspMinActX, xmax=\dspMaxActX}{}% + \setkeys*[psset]{dspData}{#1}% + \psplot[linewidth=\dspLineWidth, plotpoints=\dspPSPoints,% + linejoin=1,#1]{\dspXmin}{\dspXmax}[{#2}]{#3}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plot smooth function from a set of points +%% +%% \dspFuncData[OPTIONS]{x1 y1 x2 y2 ...} +%% +\newcommand{\dspFuncData}[2][]{% + \listplot[linewidth=\dspLineWidth,linejoin=1,plotstyle=line,#1]{\expandafter\m@keList#2 \relax}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plot smooth function from a set of points starting at a given point +%% Data in this case is only ordinates +%% +%% \dspFuncDataAt[OPTIONS]{x1}{y1 y2 ...} +%% +\newcommand{\dspFuncDataAt}[3][]{% + \listplot[linewidth=\dspLineWidth,linejoin=1,plotstyle=line,#1]{% + #2 + [#3] { % n [] + % n a0 + 1 index % n a0 n + 1 add + } forall + pop +}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plot smooth function from a data file +%% file must contain a list of space-separated abscissa and ordinate pairs +%% +%% \dspFuncFile[OPTIONS]{FILE} +%% +\newcommand{\dspFuncFile}[2][]{% + \readdata{\data}{#2}% + \listplot[linewidth=\dspLineWidth,linejoin=1,plotstyle=line,#1]{\data}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% +%% Plot Dirac deltas +%% +%% \dspDiracs[OPTIONS]{x1 y1 x2 y2 ...} +%% +\newcommand{\dspDiracs}[2][]{% + \def\dirac##1##2{\psline[linestyle=solid,linewidth=\dspLineWidth,#1]{->}(! ##1 0)(! ##1 ##2)} + \doOnPairs{dirac}{#2}} + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%% Periodize function over the [-1, 1] interval +% +\newcommand{\dspPeriod}[1]{ #1 sub #1 2 mul div dup floor sub #1 2 mul mul #1 sub } +\newcommand{\dspPeriodize}{ \dspPeriod{1} } +\newcommand{\dspMainPeriod}[1][]{% + \psframe[linecolor=lightgray,linewidth=0.4pt,#1](-1,\dspMinY)(1,\dspMaxY)} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%% Plot text +% \dspText(x,y){text} +\newcommand{\dspText}[2]{% + \rput*[B]{0}#1{#2}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%% Pole-Zero Plots +% +% Specialized options: +% +% circle=["true" | "false"] draw unit circle +% clabel="text" set a label at circle unit +% roc +% +\define@key{dspPZ}{width}{\setlength{\dspW}{#1}\setlength{\dspH}{#1}} +\define@key{dspPZ}{height}{\setlength{\dspH}{#1}} +\define@key{dspPZ}{circle}{\def\dspCircle{#1}} +\define@key{dspPZ}{clabel}{\def\dspCircleLabel{#1}} +\define@choicekey*+{dspPZ}{xticks}[\ll\ln]{auto,none}[auto]{% + \DoXTickstrue\def\incX{-1} + \ifcase\ln\relax + \relax + \or + \DoXTicksfalse + \fi}{% + \DoXTickstrue + \def\incX{#1}} +\define@choicekey*+{dspPZ}{yticks}[\ll\ln]{auto,none}[auto]{% + \DoYTickstrue\def\incY{-1} + \ifcase\ln\relax + \relax + \or + \DoYTicksfalse + \fi}{% + \DoYTickstrue + \def\incY{#1}} +\newif\ifComplexLabels +\define@choicekey*{dspPZ}{cunits}[\ll\ln]{true,false}[true]{% + \ifcase\ln\relax + \ComplexLabelstrue + \or + \ComplexLabelsfalse + \fi} +\define@key{dspPZ}{roc}{\def\PZCROC{#1}} +\define@key{dspPZ}{antiroc}{\def\PZAROC{#1}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +\newenvironment{dspPZPlot}[2][]{% + \setlength{\dspW}{\dspHeight}\setlength{\dspH}{\dspHeight}% + \ComplexLabelstrue% + \presetkeys{dspPZ}{xticks=auto,yticks=auto,circle=1,clabel={ },roc=-1,antiroc=-1}{}% + \setkeys{dspPZ}{#1}% +% + %% set up + \dspSetDims{-#2},{#2},{-#2},{#2},0\relax% + \dspSetupAxes% +% + \gdef\dspTickX##1{\psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](##1,-\tickEndX)(##1,\tickEndX)}% + \gdef\dspTickY##1{\psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](-\tickEndY,##1)(\tickEndY,##1)}% + \gdef\dspTickLabelY##1##2{\uput{{2\dspYTickGap}}[0]{{0}}(\tickEndY,##1){{##2}}}% + \gdef\dspTickLabelX##1##2{\rput[B]{{0}}(##1,\tickTxtX){{##2}}}% +% + %% start the plot + \begin{pspicture}(\LX,\BY)(\RX,\TY) + \FPifpos\PZCROC% + \pscustom[fillstyle=vlines,hatchcolor=lightgray,linecolor=lightgray,linewidth=0]{% + \psarc(0,0){\PZCROC\dspUnitX}{0}{360}% + \psline[linecolor=\dspAxisColor](\dspMaxX,0)(\dspMaxX,\dspMinY)(\dspMinX,\dspMinY)% + (\dspMinX,\dspMaxY)(\dspMaxX,\dspMaxY)(\dspMaxX,0)} + \pscircle[linecolor=lightgray,dimen=middle]{\PZCROC\dspUnitX}\relax\fi + \FPifpos\PZAROC% + \pscircle[fillstyle=vlines,hatchcolor=lightgray,linecolor=lightgray,dimen=middle]{\PZAROC\dspUnitX}\relax\fi +%% + \psline[linewidth=\dspFrameLineWidth,linecolor=\dspAxisColor](\dspMinX,0)(\dspMaxX,0)% + \psline[linewidth=\dspFrameLineWidth,linecolor=\dspAxisColor](0,\dspMinY,0)(0,\dspMaxY)% + \dspPlotFrame% + \FPifgt\dspCircle{0}% + \FPmul\r\dspCircle{\strip@pt\dspUnitX}% + \pscircle[linewidth=\dspFrameLineWidth,dimen=middle](0,0){{\r}pt}% + \ifx\@empty\dspCircleLabel% + \def\dspCircleLabel{\dspCircle}\relax\fi + \FPupn\r{0.6 \dspTSX{} mul \dspCircle{} add}% + \rput[b]{0}(\r,\tickTxtX){\dspCircleLabel}\relax\fi +% + % draw ticks selectively according to user options + % but here skip zero and intersections with the circle (if any) + \FPupn\r{\tlimX{} 1 sub 2 div clip}% + \def\xt{% + \multido{\n=\stX+\incX}{\r}{\FPifeq\n{-\dspCircle}\relax\else\dspTickX{\n}\fi}% + \multido{\n=\incX+\incX}{\r}{\FPifeq\n\dspCircle\relax\else\dspTickX{\n}\fi}% + \multido{\n=\stX+\incX}{\r}{\FPifeq\n{-\dspCircle}\relax\else\dspTickLabelX{\n}{$\n$}\fi}% + \multido{\n=\incX+\incX}{\r}{\FPifeq\n\dspCircle\relax\else\dspTickLabelX{\n}{$\n$}\fi}}% + \def\yt{% + \multido{\n=\stY+\incY}{\r}{\FPifeq\n{-\dspCircle}\relax\else\dspTickY{\n}\fi}% + \multido{\n=\incY+\incY}{\r}{\FPifeq\n\dspCircle\relax\else\dspTickY{\n}\fi}% + \multido{\n=\stY+\incY}{\r}{\FPifeq\n{-\dspCircle}\relax\else\dspTickLabelY{\n}{$\n$}\fi}% + \multido{\n=\incY+\incY}{\r}{\FPifeq\n\dspCircle\relax\else\dspTickLabelY{\n}{$\n$}\fi}}% + \ifDoXTicks\xt\fi + \ifDoYTicks\yt\fi + \ifComplexLabels% + \rput[mr]{0}(\dspMaxX,1em){Re~}% + \FPupn\r{\dspMaxY{} 0.6 \dspTSY{} mul sub}% + \rput[t]{0}(-1.2em,\r){Im~}\relax\fi +}{% + \end{pspicture}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Keyvals for poles and zeros +% +\newif\ifPZPole +\define@choicekey*[psset]{dspPZP}{type}[\ll\ln]{zero,pole}[zero]{% + \ifcase\ln\relax + \PZPolefalse + \or + \PZPoletrue + \fi} +\newif\ifPZLabel +\define@choicekey*+[psset]{dspPZP}{label}[\ll\ln]{auto,none}[auto]{% + \def\PZLabel{}\relax% + \ifcase\ln\relax + \PZLabeltrue + \or + \PZLabelfalse + \fi}{% + \PZLabeltrue + \def\PZLabel{#1}} +\define@key[psset]{dspPZP}{lpos}{\def\PZLP{#1}} +\pst@addfams{dspPZP} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%% Plot pole-zero point +% +% \dspPZPoint[OPTIONS]{RE,IM} +% +% RE, IM coordinates +% +% Options: +% +% type = ["pole" | "zero"] circle or cross (default: pole) +% label=["false" | TEXT ] the point's label (default: false) +% lpos = ANGLE label position (default: 45) +% +\newcommand{\dspPZ}[2][]{% + \presetkeys[psset]{dspPZP}{type=pole,label=auto}{}% + \setkeys*[psset]{dspPZP}{#1}% + \ifPZPole + \psdot[dotstyle=+,dotsize=1.4ex,dotscale=1.5,dotangle=45, #1](\twoArgSplit#2) \else + \psdot[dotstyle=*,dotsize=1.4ex,#1](\twoArgSplit#2) \fi + \ifx\@empty\PZLabel \def\PZLabel{$(\twoArgSplit#2)$} \fi + % tricky bug in pstricks so we can't use presetkeys for angle... Could not understand + \ifdefined\PZLP \relax \else \def\PZLP{45} \fi + \ifPZLabel \uput[\PZLP]{0}(\twoArgSplit#2){\PZLabel} \fi} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\define@key{dspCP}{width}{\setlength{\dspCPW}{#1}\setlength{\dspCPH}{#1}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% dspCP environment +% +% \begin{dspCP}[OPTIONS]{MAX} +% +% +\newlength{\dspCPW}\newlength{\dspCPH} +\newenvironment{dspCP}[3][]{% +%% scale dimensions so that axes have equal units + \setlength{\dspCPW}{0.37\textwidth}\setlength{\dspCPH}{\dspCPW} + \setlength{\dspW}{\dspCPW}\setlength{\dspH}{\dspCPH} + \setkeys*{dspCP}{#1}% + \dspSetDims#2,#3,0\relax% + \FPupn\g{\dspRngY{} {\strip@pt\dspCPW} / \dspRngX{} * 0 trunc}% + \setlength{\dspCPH}{1pt*\g}% +%% + \begin{dspPlot}[#1,sidegap=0,inticks=true,width=\dspCPW,height=\dspCPH]{#2}{#3}% + \ifYAxisExp\psline[linewidth=\dspFrameLineWidth,linecolor=\dspAxisColor](0,\dspMinY)(0,\dspMaxY)\fi +}{% +%% redo ticks and axes since images may overlap a little + \dspPlotFrame + \ifDoXTicks\multido{\n=\stX+\incX}{\tlimX}{\dspTickX{\n}}\fi + \ifDoYTicks\multido{\n=\stY+\incY}{\tlimY}{\dspTickY{\n}}\fi + \end{dspPlot}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%% Plot Dirac deltas +% +% \dspPoints[OPTIONS]{x1 y1 x2 y2 ...} +% +\newcommand{\dspPoints}[2][]{% + \listplot[plotstyle=dots,% + showpoints=true, dotstyle=*,% + dotsize=\dspDotSize, #1]{\m@keList#2 \relax}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%% Plot Dirac delta with value +% +% \dspDiracs[OPTIONS]{x, y}{text} +% +\newcommand{\dspPointValue}[3][]{% + \psdot[dotstyle=*, dotsize=\dspDotSize, #1](\twoArgSplit#2)% + \uput[45]{0}(\twoArgSplit#2){#3}} + +\newcommand{\dspPointValueSC}[3][]{% + \SpecialCoor + \psdot[dotstyle=*, dotsize=\dspDotSize, #1](#2)% + \uput[45]{0}(\twoArgSplit#2){#3} + \NormalCoor} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%% Plot image from file +\newcommand{\dspImageFile}[1]{% + \FPupn\u{2 \dspRngX{} 1.01 * / \dspMinX{} + }\FPupn\v{2 \dspRngY{} 1.01 * / \dspMinY{} + }% + \setlength{\dspCPW}{1.01\dspW}\setlength{\dspCPH}{1.01\dspH}% + \rput(\u,\v){\includegraphics[width=\dspCPW,height=\dspCPH]{#1}}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%% Quick image plot, with frame but no additional space around it +\newcommand{\dspShowImage}[2][0.37\textwidth]{% + \psset{xunit=#1,yunit=#1}% + \begin{pspicture}(0,0)(0,1)% + \includegraphics[width=#1,height=#1]{#2}% + \psframe[dimen=middle,linewidth=1.1pt](-0.01,0)(-.99,.99) + \end{pspicture}} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +%% Some geometrical primitives +% +\newif\ifPointToOrg +\define@choicekey*[psset]{dspPZP}{toorg}[\ll\ln]{true,false}[false]{% + \ifcase\ln\relax + \PointToOrgtrue + \or + \PointToOrgfalse + \fi} + +% [opts]{x,y}{label} +\newcommand{\dspCPPoint}[3][]{% + \setkeys*[psset]{dspPZP}{#1}% + \psdot[dotstyle=*, dotsize=\dspDotSize, #1](#2)% + \uput[45]{0}(#2){#3}% + \ifPointToOrg\psline[linewidth=\dspTickLineWidth, #1](0,0)(#2)\fi} + +% [opts]{x,y in special coor}{label} +\newcommand{\dspCPPointSC}[3][]{% + \setkeys*[psset]{dspPZP}{#1}% + \SpecialCoor% + \psdot[dotstyle=*, dotsize=\dspDotSize, #1](#2)% + \uput[45]{0}(#2){#3}% + \ifPointToOrg\psline[linewidth=\dspTickLineWidth, #1](! 0 0 )(#2)\fi% + \NormalCoor} + +% [opts]{x,y}{r} +\newcommand{\dspCPCircle}[3][]{% + \pscircle[#1](#2){#3\dspUnitX}} + +% [opts]{r}{a}{label} +\newcommand{\dspCPCirclePoint}[4][]{% + \setkeys*[psset]{dspPZP}{#1}% + \SpecialCoor% + \def\pcorps{! #3 cos #2 mul #3 sin #2 mul}% + \FPupn\q{#2 1.1 * 2 trunc}% + \uput*{\q\dspUnitX}[#3]{0}(0,0){#4}% + \psdot[dotstyle=*, dotsize=\dspDotSize, #1](\pcorps)% + \ifPointToOrg\psline[linewidth=\dspTickLineWidth, #1](! 0 0 )(\pcorps)\fi% + \NormalCoor} + +% [opts] {r}{a}{b}{label} +\newcommand{\dspCPArc}[5][]{% + \FPupn\p{#3 #4 + 0.5 * 2 trunc}% + \FPupn\q{#2 1.1 * 2 trunc}% + \uput*{\q\dspUnitX}[\p]{0}(0,0){#5}% + \psarc[linewidth=2\dspTickLineWidth, #1]{->}{#2\dspUnitX}{#3}{#4}} +\newcommand{\dspCPArcn}[5][]{% + \FPupn\p{#3 #4 + 0.5 * 2 trunc}% + \FPupn\q{#2 1.1 * 2 trunc}% + \uput*{\q\dspUnitX}[\p]{0}(0,0){#5}% + \psarcn[linewidth=2\dspTickLineWidth, #1]{->}{#2\dspUnitX}{#3}{#4}} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Helpers +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This is called at each plot setup with xmin, xmax, ymin, ymax and sidegap +%% and sets all lengths +\def\dspSetDims#1,#2,#3,#4,#5\relax{% + \def\sideGap{#5}% + % default sidegap: 5% of range + \FPifneg\sideGap\FPupn\sideGap{#1 #2 - 0.05 * 0.5 + 2 trunc}\fi% + \FPifgt\sideGap{1}\FPtrunc\sideGap\sideGap{0}\fi% +%% +%% active range for the independent variable + \def\dspMinActX{#1}% + \def\dspMaxActX{#2}% +%% axes range (including sidegap) + \FPupn\dspMinX{\sideGap{} #1 - clip}% + \FPupn\dspMaxX{\sideGap{} #2 + clip}% + \FPupn\dspRngX{#1 #2 - \sideGap{} 2 * + clip}% + \FPupn\dspMinY{#3 0 + clip}% + \FPupn\dspMaxY{#4 0 + clip}% + \FPupn\dspRngY{#3 #4 - clip}% +%% +% if y-range is across zero we'll need to draw the x-axis + \FPmul\u\dspMinY\dspMaxY% + \FPifneg\u\XAxisExptrue\else\XAxisExpfalse\fi% +%% same for x (but usually we never draw the y axis) + \FPmul\u\dspMinX\dspMaxX% + \FPifneg\u\YAxisExptrue\else\YAxisExpfalse\fi% +%% +%% pstricks units: we scale the units so that coordinates are "real" coords on the axes + \FPupn\tmp{\dspRngX{} {\strip@pt\dspW} / } + \setlength{\dspUnitX}{\tmp pt}% + \FPupn\tmp{\dspRngY{} {\strip@pt\dspH} / }% + \setlength{\dspUnitY}{\tmp pt}% +%% +%% basic unit based on the size of the image: ~1pt for a 10x5 cm box + \FPupn\g{2 {\strip@pt\dspW} {\strip@pt\dspH} * root 0.005 * 0 round 1 max}% + \setlength{\dspBU}{1pt*\g}% +%% derived sizes: lines and fonts + \setlength{\dspLineWidth}{1.8\dspBU}% + \setlength{\dspDotSize}{5\dspBU}% + \setlength{\dspStemWidth}{1.4\dspBU}% + \fontsize{9\dspBU}{10\dspBU}\selectfont% +% %% ticks on axes + \setlength{\dspTickLen}{4\dspBU}% + \setlength{\dspTickLineWidth}{0.4\dspBU}% + \setlength{\dspXTickGap}{6\dspBU}\addtolength{\dspXTickGap}{2ex}% + \setlength{\dspYTickGap}{2\dspBU}% + \setlength{\dspFrameLineWidth}{2.2\dspTickLineWidth}% +%% +%% height of a line of text in psticks units + \setlength{\dspTmpLen}{1em}% + \FPupn\dspTSX{{\strip@pt\dspUnitX} {\strip@pt\dspTmpLen} / }% + \FPupn\dspTSY{{\strip@pt\dspUnitY} {\strip@pt\dspTmpLen} / }% +%% +%% find the coordinates of the plot's bounding box, including labels + \ifYLabel% + \FPupn\LX{\dspTSX{} 4 * \dspMinX{} -}% + \FPupn\RX{\dspTSX{} 4 * \dspMaxX{} +}% + \else% + \FPupn\LX{\dspTSX{} 2 * \dspMinX{} -}% + \FPupn\RX{\dspTSX{} 2 * \dspMaxX{} +}% + \fi + \FPupn\TY{\dspTSY{} \dspMaxY{} +}% + \def\outTicks{% + \ifXTicks\FPupn\BY{\dspTSY{} 2.5 * \dspMinY{} -}\else\FPupn\BY{\dspTSY{} \dspMinY{} -}\fi% + \ifXLabel\FPupn\BY{\dspTSY{} 1.5 * \BY{} -}\else\relax\fi }% + \ifXAxisExp % ticks are inside + \ifXLabel\FPupn\BY{\dspTSY{} 2.5 * \dspMinY{} -}\else\FPupn\BY{\dspTSY{} \dspMinY{} -}\fi% + \else% ticks are outside + \outTicks \fi% + % did we select explicit outside ticks? + \ifXTicksOut\outTicks \fi% +%% +%% x-axis resolution for plotting functions: ~60 values/cm + \FPupn\dspPSPoints{{\strip@pt\dspW} 2 * 0 trunc}% +%% + \psset{xunit=\dspUnitX, yunit=\dspUnitY}% + \psset{linewidth=\dspLineWidth}%www +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Draw axis labels (if required) under x axis and to left and right of y axes +%% +\def\dspLabels{% + % horizontal label + \ifXTicksOut\XAxisExpfalse\fi% + \ifXLabel% + \FPupn\mid{\dspMinX{} \dspMaxX{} + 0.5 mul}% + \ifXAxisExp% + \FPupn\pos{\dspTSY{} 2 * \dspMinY{} -}% + \else% + \ifXTicks% + \FPupn\pos{\dspTSY{} 3 * \dspMinY{} -}% + \else% + \FPupn\pos{\dspTSY{} 2 * \dspMinY{} -}% + \fi% + \fi% + \rput[b]{0}(\mid,\pos){\dspXLabel}% + \fi% +% + \FPupn\mid{\dspMinY{} \dspMaxY{} + 0.5 mul}% + \ifYTicks% + \FPupn\pos{\dspTSX{} 3.4 * \dspMinX{} -}% + \else% + \FPupn\pos{\dspTSX{} 1 * \dspMinX{} -}% + \fi% + \rput[b]{90}(\pos,\mid){\dspYLabel} +%% + \FPupn\pos{\dspTSX{} 3 * \dspMaxX{} +}% + \rput[b]{-90}(\pos,\mid){\dspYLabelR}} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% This sets axes ticks (spacing and number) and prepares macros +%% for plotting ticks and tick labels +\def\dspSetupAxes{% +%% tick increments; if incX/Y is zero, compute suitable value + \FPifgt\incX{0}\FPupn\incX{\incX{} 2 trunc}% + \else\FPupn\incX{\dspMinActX{} \dspMaxActX{} - 1 + 6 swap / 0 trunc 1 max}\relax\fi% + \FPifgt\incY{0}\FPupn\incY{\incY{} 2 trunc}% + \else\FPupn\incY{\dspMinY{} \dspMaxY{} - 1 + 6 swap / 0 trunc 1 max}\relax\fi% +%% +%% now find starting point and increment for ticks (and number of ticks) +%% start with y-axis: + \ifXAxisExp% is y=0 explicit or does it coincide with the lower edge? + \def\haY{0}% + % make sure ticks hit zero; add small epsilons to avoid ticks at the limits + \FPupn\stY{\incY{} \dspMinY{} / 0.001 + 0 trunc \incY{} * 2 trunc}% + \FPupn\tlimY{\stY{} \dspMaxY{} - 0.001 - \incY{} swap / abs 1 + 0 trunc}% + \else% + \def\haY{\dspMinY}% + \FPupn\tlimY{\incY{} \dspRngY{} / abs 1 + 0 trunc}% + \FPupn\stY{\dspMinY{} 2 trunc}% \incY{} 1 \tlimY{} - * \dspRngY{} - 0.5 * \dspMinY{} + 2 trunc}% + \fi% + % x-ticks outside of the box anyway? + \ifXTicksOut\def\haY{\dspMinY}\relax\fi% + % round off to integer if possible: + \FPupn\v{\stY{} 0 trunc \stY{} - abs \incY{} 0 trunc \incY{} - abs + clip}% + \FPifeq\v{0}\FPtrunc\stY\stY{0}\FPtrunc\incY\incY{0}\relax\fi% +% +%% now x-axis: + \ifYAxisExp% we almost never draw the y-axis but need to see if x-axis spans zero + % make sure ticks hit zero; add small epsilons to avoid ticks at the limits + \FPupn\stX{\incX{} \dspMinX{} / 0 trunc \incX{} * 2 trunc}% + \FPupn\tlimX{\incX{} \stX{} \dspMaxX{} - / abs 1 + 0 trunc}% + \else% + \FPupn\tlimX{\incX{} \dspRngX{} / abs 1 + 0 trunc}% + \FPupn\stX{\dspMinX{} 2 trunc}% \FPupn\stX{\incX{} 1 \tlimX{} - * \dspRngX{} - 0.5 * \dspMinX{} + 2 trunc}% + \fi% + \FPupn\v{\stX{} 0 trunc \stX{} - abs \incX{} 0 trunc \incX{} - abs +}% + \FPifzero\v\FPtrunc\stX\stX{0}\FPtrunc\incX\incX{0}\relax\fi% +%% +%% macros for drawing x-ticks + \ifXInside% + \FPupn\tickEndX{{\strip@pt\dspUnitY} {\strip@pt\dspTickLen} /}% + \FPupn\tickTxtX{{\strip@pt\dspUnitY} {\strip@pt\dspXTickGap} 0.9 * / \dspMinY{} -}% tick label pos in PS units + \FPupn\tickXB{\tickEndX{} \dspMinY{} +}% + \FPupn\tickXT{\tickEndX{} \dspMaxY{} -}% + \gdef\dspTickX##1{% + \psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](##1,\dspMinY)(##1,\tickXB)% + \psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](##1,\dspMaxY)(##1,\tickXT)}% + % \gdef\dspTickLabelX##1##2{\uput{{2\dspYTickGap}}[180]{{0}}(\dspMinX,##1){{##2}}}% + \gdef\dspTickLabelX##1##2{\rput*[B]{{0}}(##1,\tickTxtX){{##2}}}% + \else% + \FPupn\tickEndX{{\strip@pt\dspUnitY} {\strip@pt\dspTickLen} / \haY{} -}% tick len in PS units + \FPupn\tickTxtX{{\strip@pt\dspUnitY} {\strip@pt\dspXTickGap} / \haY{} -}% tick label pos in PS units + \gdef\dspTickX##1{\psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](##1,\haY)(##1,\tickEndX)}% + \gdef\dspTickLabelX##1##2{\rput*[B]{{0}}(##1,\tickTxtX){{##2}}}% + \fi% +%% macros for drawing y-ticks + \FPupn\tickEndY{{\strip@pt\dspUnitX} {\strip@pt\dspTickLen} /}% + \FPupn\tickXB{\tickEndY{} \dspMinX{} +}% + \FPupn\tickXT{\tickEndY{} \dspMaxX{} -}% + \gdef\dspTickY##1{% + \psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](\dspMinX,##1)(\tickXB,##1)% + \psline[linewidth=\dspTickLineWidth,linecolor=\dspAxisColor](\dspMaxX,##1)(\tickXT,##1)}% + \gdef\dspTickLabelY##1##2{\uput{{2\dspYTickGap}}[180]{{0}}(\dspMinX,##1){{##2}}}% + \gdef\dspTickLabelYR##1##2{\uput{{2\dspYTickGap}}[0]{{0}}(\dspMaxX,##1){{##2}}}% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% simplify fractions of pi +\newcount\dspNum \newcount\dspDen +\def\simplifyPiFrac#1#2{% + \ifnum#1=0 $0$\else % zero is zero + \dspNum=#1 \dspDen=#2 % + \divide\dspNum by\dspDen \multiply\dspNum by\dspDen % see if frac is simply an integer + \ifnum\dspNum=#1 \divide\dspNum by\dspDen \ifnum\dspNum=1 $\pi$\else \ifnum\dspNum=-1 $-\pi$\else $\number\dspNum\pi$\fi\fi\else% + \dspNum=#1 % + \ifnum\dspNum<0 \multiply\dspNum by-1 \def\s{-}\else\def\s{}\fi % normalize sign + \divide\dspDen by\dspNum \multiply\dspDen by\dspNum % see if frac is of type 1/x + \ifnum\dspDen=#2 \divide\dspDen by\dspNum $\s\pi / \number\dspDen$\else % + \dspNum=#1\dspDen=#2 % + \removeFactor{10}\removeFactor{9}\removeFactor{8}% remove some common factors + \removeFactor{7}\removeFactor{6}\removeFactor{5}% + \removeFactor{4}\removeFactor{3}\removeFactor{2}% + $\number\dspNum \pi / \number\dspDen$\fi% + \fi % + \fi} + +%% simplify a fraction (not the full Euclid, but it's ok for our purposes) +\newcount\dspTerm \newcount\dspFact +\def\removeFactor#1{\dspFact=#1 \dspTerm=\dspNum% + \divide\dspTerm by\dspFact \multiply\dspTerm by\dspFact % + \ifnum\dspTerm=\dspNum % + \dspTerm=\dspDen % + \divide\dspTerm by\dspFact \multiply\dspTerm by\dspFact % + \ifnum\dspTerm=\dspDen % + \divide\dspNum by\dspFact \divide\dspDen by\dspFact % + \fi % + \fi} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% space-separated lists must have at least two pairs of elements. +% Duplicate singletons +% +\def\m@keList#1 #2 #3\relax{% + \ifx& + #1 #2 #1 #2 + \else + #1 #2 #3 + \fi +} + +\def\twoArgSplit#1,#2{#1, #2} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% prepend the ordinal index to each element of a space-separated list +% +\def\m@keIndexedList#1#2{% + \count0=#1% + \expandafter\m@kixl\trim #2 |} +\def\m@kixl#1 {% + \ifx#1|% + \let\next=\relax% + \else{\number\count0} \ #1\ \advance\count0 by1\let\next=\m@kixl\fi% +\next} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% perform an action on all consecutive pairs in a space-separated list +% +\def\doOnPairs#1#2{% + \def\action{#1}% + \expandafter\p@rseB\trim #2 |} +\def\p@rseB#1 #2 #3{% + \csname \action\endcsname{#1}{#2}% + \ifx#3|% + \let\next=\@gobble% + \else% + \let\next=\p@rseB\fi% + \next #3} +\def\@gobble#1{} + + +\def\trim#1{% + \romannumeral-`\.\expandafter\noexpand#1% +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% +% PsTricks overrides +% +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%% Lollipop line style, by Denis.Girou at idris.fr %%%%%%%%%%%%%%%%%%%%%%%% +%% +\let\beginplot@LineToXAxis\beginplot@line +\def\endplot@LineToXAxis{\psLineToXAxis@ii} +\let\beginqp@LineToXAxis\beginqp@line +\let\doqp@LineToXAxis\doqp@line +\let\endqp@LineToXAxis\endqp@line +\let\testqp@LineToXAxis\testqp@line +% +\def\psLineToXAxis@ii{% +\addto@pscode{\pst@cp \psline@iii \tx@LineToXAxis}% +\end@OpenObj} +% +\def\tx@LineToXAxis{LineToXAxis } +% +% Adapted from Line +\pst@def{LineToXAxis}<{% +NArray +n 0 eq not + { n 1 eq { 0 0 /n 2 def } if + ArrowA + /n n 2 sub def + CP 2 copy moveto pop 0 Lineto + n { 2 copy moveto pop 0 Lineto } repeat + CP + 4 2 roll + ArrowB + 2 copy moveto pop 0 + L + pop pop } if}> + + +\makeatother +\endinput + diff --git a/Master/tlpkg/bin/tlpkg-ctan-check b/Master/tlpkg/bin/tlpkg-ctan-check index fedfe34b05c..51b9d0e935e 100755 --- a/Master/tlpkg/bin/tlpkg-ctan-check +++ b/Master/tlpkg/bin/tlpkg-ctan-check @@ -166,7 +166,7 @@ my @TLP_working = qw( doi doipubmed dosepsbin dot2texi dotarrow dotseqn dottex doublestroke dowith download dox dozenal dpfloat dprogress drac draftcopy - draftwatermark dramatist dratex drawstack droid droit-fr drs drv + draftwatermark dramatist dratex drawstack droid droit-fr drs drv dsptricks dtk dtxgallery dtxgen dtxtut duerer duerer-latex duotenzor dutchcal dvdcoll dvgloss dviasm dviincl dvipdfmx-def diff --git a/Master/tlpkg/tlpsrc/collection-pstricks.tlpsrc b/Master/tlpkg/tlpsrc/collection-pstricks.tlpsrc index c68f8b02f4d..e2ab83864ca 100644 --- a/Master/tlpkg/tlpsrc/collection-pstricks.tlpsrc +++ b/Master/tlpkg/tlpsrc/collection-pstricks.tlpsrc @@ -7,6 +7,7 @@ depend collection-genericrecommended # depend auto-pst-pdf depend bclogo +depend dsptricks depend makeplot depend pdftricks depend pdftricks2 diff --git a/Master/tlpkg/tlpsrc/dsptricks.tlpsrc b/Master/tlpkg/tlpsrc/dsptricks.tlpsrc new file mode 100644 index 00000000000..e69de29bb2d -- cgit v1.2.3