7 Utilities
Signals and Systems provides a variety of operations that are useful for signal processing, but are extensions of the included functionality that are difficult to classify. These utilities provide features such as connectivity with other packages, enhancements to TeX formatting, polygon manipulation, and more.
7.1 Polygon Manipulation
The utilities in Signals and Systems for manipulating polygons are most useful in the context of twodimensional signal processing. Many of these routines are used internally by decimation system design routines and analysis of downsampling. Most of the routines can only be used with twodimensional convex polygons.
Computations with polygons.
Several simple geometric manipulations with polygons are included with these utilities. These determine whether a polygon is convex, whether a point is inside a given polygon, and the area of a given polygon. InsidePolygonQ includes the option BoundaryInside to determine whether a point on the boundary is considered to be inside the polygon or not.
A function for finding antipodal pairs also exists. An antipodal pair is an edge of a polygon and a corresponding vertex, for which a line through the edge and another line through the vertex that is parallel to the edge do not cross through any part of the polygon, but remain tangent. Any given edge may have more than one corresponding antipodal vertex, but the algorithm returns only one (the first found by proceeding clockwise about the polygon from the vertex of the previous antipodal pair). The polygon must be convex; this guarantees that an antipodal pair exists for each edge.
First, verify that the signal processing functions are accessible.
In[1]:=Needs["SignalProcessing`"]
Is the polygon convex?
In[2]:=ConvexPolygonQ[ Polygon[{{1, 1}, {0,0}, {0,1}, {1, 1}}] ]
Out[2]=
Is the point inside the triangle?
In[3]:=InsidePolygonQ[ Polygon[{{1, 1}, {0, 1}, {1, 1}}], Point[{0, 0}] ]
Out[3]=
The result is easily verified.
In[4]:=Show[Graphics[ {Polygon[{{1, 1}, {0, 1}, {1, 1}}], GrayLevel[0.8], PointSize[.05], Point[{0, 0}]} ]]
Out[4]=
This defines a polygon we will use in some computations.
In[5]:=apoly = Polygon[ {{1, 0}, {0, .5}, {1, 0}, {1,1}, {.5, 1.5}, {.5, 1.5}, {1, 1}} ];
Here is the area of the polygon we just created.
In[6]:=PolygonArea[apoly]
Out[6]=
Here are the antipodal pairs generated from the polygon we created.
In[7]:=appairs = AntipodalPairs[apoly]
Out[7]=
Here we see two lines generated from one of the antipodal pairs. Note how the polygon lies completely between the two lines. One of the lines runs through an edge of the polygon, while the other passes through the corresponding antipodal vertex. These lines are parallel by definition.
In[8]:=Show[Graphics[{apoly, Hue[0], Thickness[0.02], Function[{vec, p1, p2}, {Line[{p1  2 vec, p1 + vec}], Line[{p2  vec, p2 + vec}]} ] @@ {#[[1,1,1]]  #[[1,1,2]], #[[1,1,1]], #[[2,1]]}&[First[appairs]] }]]
Out[8]=
Manipulations with polygons that return polygons.
Several other of the polygon operations return new polygons. PolygonToTriangles breaks up the polygon in question into triangles, which is useful for a number of computations. This operation can be performed on polygons in three dimensions (though not general polyhedra). Note that the triangulation is not the same as that performed by some Mathematica graphics routines. The triangulation is defined around the "center of mass" of the polygon.
ConvexPolygonIntersection determines the mutual intersection of the input convex polygons. The input can contain lists of polygons.
The minimum rectangle surrounding a given polygon can be found by MinimalEnclosingRectangle. Note that this rectangle is not necessarily unique. The minimum arbitrary parallelogram circumscribing a polygon can be found via MinimalEnclosingParallelogram. Where MinimalEnclosingRectangle uses a quadratictime algorithm, MinimalEnclosingParallelogram uses a lineartime method.
A plane can be mapped so that each point on the plane is mapped into a rectangle. This is equivalent to tiling the rectangle to cover the plane. It is used in twodimensional signal processing to represent the fundamental frequency tile. The function ConvexPolygonModRectangle transforms a convex polygon (or list of such polygons) into a list of polygons that lie within the bounds of the fundamental tile. The tile is represented by a pair of points giving the lowerleft and upperright corners of the rectangle, as in {{xmin, ymin}, {xmax, ymax}}. If it is not specified, it is assumed to be over the range {{Pi, Pi}, {Pi, Pi}}.
Here is a set of triangles defining the polygon we gave earlier.
In[9]:=PolygonToTriangles[apoly]
Out[9]=
When visualized, we note that the triangles are formed by joining the vertices of the polygon to its centroid. Hence, a convex polygon is required.
In[10]:=Show[Graphics[ {GrayLevel[.8], apoly, GrayLevel[0], Thickness[.02], %/.Polygon[{a__, b_}] :> Line[{b, a, b}] } ]]
Out[10]=
We now find the intersection of the input polygons.
In[11]:=intersect = ConvexPolygonIntersection[ Polygon[{{0,0},{1,0},{0,1}}], Polygon[{{.5, .5}, {.5,.5}, {.5, .5}, {.5, .5}}], Polygon[{{0,0}, {.8, 1}, {1, .8}}] ]
Out[11]=
We can examine the intersection graphically.
In[12]:=Show[Graphics[{ GrayLevel[.4], Polygon[{{0,0},{1,0},{0,1}}], GrayLevel[.6], Polygon[{{.5, .5}, {.5,.5}, {.5, .5}, {.5, .5}}], GrayLevel[.8], Polygon[{{0,0}, {.8, 1}, {1, .8}}], GrayLevel[0], intersect }]]
Out[12]=
Create another polygon.
In[13]:=poly = Polygon[{{0,0}, {0.5, 0.7}, {0.7, 0.8}, {1, 0.8}, {0.4, 0.2}}];
This is the minimum rectangle around the input polygon.
In[14]:=mrect = MinimalEnclosingRectangle[ poly ]
Out[14]=
This is the minimum paralellogram around the polygon.
In[15]:=mpara = MinimalEnclosingParallelogram[ poly ]
Out[15]=
We can compare visualizations of the polygons.
In[16]:=Show[GraphicsArray[{ Graphics[{mrect, GrayLevel[.8], poly}, AspectRatio > Automatic, PlotRange > {{0.2, 1.2}, {0.2, 1.2}}], Graphics[{mpara, GrayLevel[.8], poly}, AspectRatio > Automatic, PlotRange > {{0.2, 1.2}, {0.2, 1.2}}] }]]
Out[16]=
Comparison of the areas shows that the minimal parallelogram is smaller and will lead to better compression ratios than the minimal rectangle.
In[17]:={PolygonArea[mrect], PolygonArea[mpara]}
Out[17]=
This polygon does not lie entirely within the specified rectangle. Hence, it is broken into pieces that are shifted to lie within the rectangle.
In[18]:=ConvexPolygonModRectangle[ Polygon[{{0.3, 0.6}, {0.5, 1.4}, {0.6, 0.6}}], {{0,0}, {1,1}} ]
Out[18]=
This visualization shows the rectangle, the wrapped parts of the triangle, and the outline of the original shape.
In[19]:=Show[Graphics[{ GrayLevel[0.8], Rectangle[{0,0}, {1,1}], GrayLevel[0.3], %, GrayLevel[0], Line[{{0.3, 0.6}, {0.5, 1.4}, {0.6, 0.6}, {0.3, 0.6}}] }], AspectRatio > Automatic]
Out[19]=
Functions for generating distinct colors.
Two additional functions are included to provide utility in the creation of graphics. These create lists of distinct colors of the specified type. The colors are not random, but instead are spaced as far apart as possible in the color space, while also remaining distinct from black and white. The colors can be used in plot styles.
Here are five different RGB colors.
In[20]:=DistinctRGBColors[5]
Out[20]=
This creates eight different CMYK colors.
In[21]:=DistinctCMYKColors[8]
Out[21]=
7.2 Linking to Ptolemy
Ptolemy is a freely distributable signal processing design and simulation package from the University of California at Berkeley. It includes a graphical programming environment, hierarchical dataflow representations of signal processing systems, and DSP assembly code generation among many other features. Signals and Systems provides functionality to export a system description to Ptolemy, so that it may be used in various sorts of simulation and code generation.
Commands to write the Ptolemy form of a system.
PtolemyForm is a formatting command that represents the signal processing expression in the Ptolemy language. This expression can be inserted into Ptolemy code for use in simulations. The command WritePtolemySimulation creates an entire readytorun simulation, with specified variables used as inputs that will increment over their specified ranges during the simulation.
Here is a simple system, formatted for use in Ptolemy.
In[22]:=PtolemyForm[ Shift[5, n][ Upsample[3, n][ Interleave[n][Sin[n], Cos[n]] ] ] ]
Out[22]=
WritePtolemySimulation will take a filename in the form of a string or an already opened stream as its first argument. The PtolemyForm of the expression is written to the stream with additional information, such as a header, settings for inputs and outputs, etc., added to the stream. Several options can be used to control this further.
Options for WritePtolemySimulation.
If the PtolemyHeader option is specified, a particular header is loaded. This should be the filename of the desired header file. If it is not given, then the header for the specified version is loaded in the simulation. Currently, only a header for use with Ptolemy 0.5 is included with Signals and Systems.
The Justification option acts as it does in many other functions.
You can use the Plot option to specify that the generated program contain code to direct the simulation output to a Ptolemy plotting routine.
For more information about Ptolemy, examine the FTP site ptolemy.eecs.berkeley.edu, use the World Wide Web at http://ptolemy.eecs.berkeley.edu, or read the comp.softsys.ptolemy news group.
7.3 TeX Formatting
Signals and Systems has enhanced the standard Mathematica facility for TeX formatting. Formatting commands for all the included signal processing operators allow you to easily place the results of computations in publicationquality documents.
Generating TeX formatting for signal processing expressions.
This is the TeX form of a signal processing expression.
In[23]:=TeXForm[ ZTransform[n, z][Shift[1, n][ Upsample[3, n][Sin[2 n]]]] ]
Out[23]//TeXForm={\cal Z}_{{n\rightarrow z}}(\Muserfunction{Shift}_{1,n}( \uparrow_{3,n}(\sin (2\,n))))
When placed in a TeX document, the preceding example will look like the following formula.
This conversion can be used by hand or in conjunction with functions like Splice to quickly prepare visually appealing documents from your computations. You may need to take advantage of the TeX style sheet notebook.sty for the TeX macros to render properly. This style sheet is included with all Mathematica distributions.
7.4 Miscellanea
There are a variety of functions in Signals and Systems that are not easily classified as being in a particular category. These functions are individually documented in this section.
A signal simplification function.
SimplifySignal applies a variety of rules and the standard Mathematica function Simplify to attempt to reduce the expression to primitive signals and systems. The expression is transformed by these rules until it stops changing. Note that unlike Simplify, it does not attempt to determine a signal with minimal leaf count, but instead applies heuristic rules in an attempt to attain a more convenient form, which may not actually have a smaller leaf count. This is particularly true when rewriting expressions with the assumption that some symbols are realvalued. It is tuned to simplify the output of transforms.
Here is a signal that can be simplified considerably.
In[24]:=SimplifySignal[ Cos[t] Sinc[t]  Sinc[2 t] + a ContinuousPulse[12, t  2] * Periodic[8, t][ContinuousPulse[2,t]] ]
Out[24]=
Options to SimplifySignal.
Two options can be employed that are specific to SimplifySignal. Any options valid for Simplify can also be passed through. The Justification option allows some information about intermediate steps in the manipulation of the signal to be printed out. You can use the RealVariables option to note that certain symbols are realvalued; special manipulation rules are then brought into play that handle this particular case.
Here is a signal being simplified and displayed with the steps taken in the process.
In[25]:=SimplifySignal[ Downsample[3, n][ Upsample[5, n][5 DiscreteDelta[n]] ], Justification > All ]
Out[25]=
Rules specific to a real variable are used here. Note that the resulting expression is not actually simpler than the original expression, but may be more useful for certain manipulations.
In[26]:=SimplifySignal[ Sin[a t]^3/t^2 + 2 Sign[3 t] + 2, RealVariables > {t} ]
Out[26]=
Programmer's utilities.
IntegerValued is very similar to IntegerQ. It returns True if the input expression is an integer, and False if it is a number that is not an integer. Unlike IntegerQ, it will remain unevaluated if the input is a symbolic expression.
This is an integer.
In[27]:=IntegerValued[5]
Out[27]=
This may or may not be an integer, so the expression remains unevaluated.
In[28]:=IntegerValued[x]
Out[28]=
IntegerVectorQ is a simple enhancement to the standard Mathematica test functions. It returns True if its argument is an integer vector, and False otherwise. Note that IntegerVectorQ is functionally equivalent to VectorQ[expr, IntegerQ].
This input does not contain an integer vector.
In[29]:=IntegerVectorQ[ {a, 5, 3, 2.3, 1} ]
Out[29]=
Here is a valid integer vector.
In[30]:=IntegerVectorQ[ Table[Random[Integer, {1, 10}], {10}] ]
Out[30]=
Formatting exponentials.
In Mathematica, negative exponentials that are factors in a product are generally formatted so they appear in the denominator of the expression. This is contrary to the formatting found in many engineering texts. As a convenience, Signals and Systems provides formatting for expressions of this type in the more usual engineering form. This is a global state set by EngineeringExponentialFormat[On]. Formatting can be returned to the usual Mathematica form by EngineeringExponentialFormat[Off]. The current state of the switch can be determined by giving an empty argument.
Here is the current state of exponential formatting.
In[31]:=EngineeringExponentialFormat[]
Out[31]=
Here is an expression with negative exponents in products.
In[32]:=expr = Plus @@ Table[n 10^(a n), {a, 3, 3}]
Out[32]=
This activates the formatting code.
In[33]:=EngineeringExponentialFormat[On]
Out[33]=
We see that the exponentials are now given as negatives.
In[34]:=expr
Out[34]=
Comparison of expressions.
To assist in forming an interactive experience with courseware based on Signals and Systems, we find the ExpressionMatch function. It is designed to enhance automated checking of results and determine, in some structural sense, how far a result given by a student diverges from the desired answer.
It is given two expressions: the student's answer, and the target expected output. It returns the student's answer with False[n] substituted for any part of the input that differs from the expected result.
Let us suppose that this is the input a student gives for a particular problem.
In[35]:=ans = ZTransform[(n1 + n2)! * (4/5)^n1 (3/7)^n2 * DiscreteStep[n1, n2]/ (n1! n2!), {n1, n2}, {z1, z2} ]
Out[35]=
Here is a comparison with an expected result. In a realistic situation, the target result would probably be acquired from a precomputed collection of expressions.
In[36]:=ExpressionMatch[ ans, ZTransform[(n1 + n2)! * (4/5)^n1 (2/7)^n2 * DiscreteStep[n1, n2]/ (n1! n2!), {n1, n2}, {z1, z2} ] ]
Out[36]=
We can employ various techniques for examining the result. Here we count the instances of False that appear in the result, and we determine their positions.
In[37]:={Count[%, _False, Infinity], Position[%, _False]}
Out[37]=
Options to ExpressionMatch.
There are two options to ExpressionMatch. Tolerance lets you specify how close two numbers must be to be treated as identical for the purposes of this comparison. The value given is the percentage difference between the values. The default is 0.05. The Variables option allows certain symbols in the target expression to be matched by any symbol in the same position in the input expression. This allows the student to use different variable names than the instructor.
This expression does not match the input.
In[38]:=ExpressionMatch[ Exp[.36 x], Exp[.34 x] ]
Out[38]=
Now the numeric value is within tolerance.
In[39]:=ExpressionMatch[ Exp[.36 x], Exp[.34 x], Tolerance > 0.1 ]
Out[39]=
Here the student used the symbol y instead of z.
In[40]:=ExpressionMatch[ Exp[3 y I], Exp[3 z I], Variables > {z} ]
Out[40]=
The Variables option only allows symbols to be matched, not arbitrary expressions.
In[41]:=ExpressionMatch[ Exp[3 Sin[z] I], Exp[3 z I], Variables > {z} ]
Out[41]=
