editz.m version 01Jul23
(Tinkering in the z plane)


Author: Paul Mennen
Email:  paul@mennen.org


Overview

Although you could design digital filters with this application, there are hundreds of other tools better suited to that task. On the other hand, editz is more focused on helping you learn to think in the z-plane or develop an intuition about how the roots of the transfer function affect the frequency response. The key feature of editz that will help you develop this intuition is the ability to grab hold of a pole or zero with the mouse and slide it around the z-plane while watching how this affects the frequency response. As soon as you used editz for the first time you will quickly recognize the value of this instantaneous feedback.

To benefit from this application, you will need at least a rudimentary understanding transfer functions and their depiction in the z-plane. There are hundreds of books that can help you with that, but if you are a beginner in this area, one recommendation I can make is Sitler's Notes - one of the first papers ever written discussing the z-plane for system analysis. Although this paper was never officially published, you can find it on my website (www.mennen.org) in the section titled "Signal processing papers".

Starting

Begin by typing editz in the Matlab command window. When you start editz for the first time, it will initialize the transfer function to:


Note that the numerator polynomial is 5th order and the denominator polynomial is 4th order so there will be 5 zeros and 4 poles. (Two of those zeros and two of those poles are below the x-axis, so they are not shown on the pole/zero plot.) There isn't anything particularly special about this transfer function ... it was just chosen so that you will have something more interesting to start with than a flat transfer function. After the first time, editz will start up showing the transfer function that was in effect the last time you pressed the "save" button.

This is the figure window you will see after starting editz with the above default transfer function:



The top plot (Transfer function)

The top plot shows the dB magnitude (green trace) and wrapped phase (purple trace) of the transfer function. The position of the cursor shown above is at x = 0.25 (i.e. one-quarter of the sampling frequency) which represents an angular frequency of pi/2 (or 90 degrees) which is shown just to the left of the x cursor readout. The y cursor readout shows that the magnitude is 3.37658 dB below the peak value (or 67.8 percent of the peak value, as shown below the traceID box to the left of the plot.) The y cursor readout (in purple) also shows that the wrapped phase is 135 degrees. Of course, these cursor readouts will change as you slide the cursor left or right. You can move the cursor one position right or left by clicking on the x-axis label ("Fraction of sample rate") with the left or right mouse button, and you can hold the mouse down to see the cursor slide slowly left or right. If you would like to see the magnitude or phase trace alone, click on "Mag" or "Phase" in the traceID box to the left of the plot.

The bottom plot (Pole/Zero plot)

The blue help text in the middle of the pole/zero plot tells you how to use the mouse to move/add/remove roots (i.e a pole or zero). This text disappears as soon as you click anywhere on the pole/zero plot or if you click on any of the buttons to add or remove a root. If you want to see the help message again, just click on the green "quick help" tag just below the TraceID box.

Try clicking on any root.

Notice that a diamond shape marker appears on top of the root indicating that you can now move this root to a new location by dragging it with the mouse. Observe that while you are dragging the root to a new location the top plot is being continuously updated to reflect the transfer function magnitude and phase associated with the pole/zero plot. (This is the signature feature of editz.) When you release the mouse button, the diamond marker will disappear but will reappear as soon as you click on another root that you wish to move. Note that when you are moving a root, you are actually moving a pair of roots (complex conjugate pairs) unless the root is on the x axis. This ensures that the polynomial coefficients are always real.

Often when you are moving a zero, you may want to place the zero on the unit circle since this results in a symmetric numerator polynomial. To make this easier, there is a "snap to" region shown in green around the unit circle. When you move the zero inside this snap to region, the zero jumps to the nearest position that is exactly on the unit circle. If you want to change the thickness of the snap to region, adjust the "Tolerance" slider in the far lower left corner of the figure. (To disable the snap to feature, simply move the tolerance slider to 0.)

Likewise, when you are moving either a zero or a pole, often you will want to place it on the real axis. To make this easier, as you move the root inside the green tolerance band along the X axis, the root will snap to the real axis. Note that as you snap a root onto the real axis, the number of coefficients in the corresponding polynomial will decrease by one since the root no longer has a corresponding complex conjugate location. (You will also see the number of zeros or poles change in the TraceID box just to the left of the Yaxis label.) Note that as you are moving the root, the x/y cursor readout shows the real and imaginary components of the root respectively and the polar representation (i.e. magnitude/phase) is shown in parenthesis to the right of the x cursor readout - (0.743, 172.04 degrees) in this example.

To add a new pole or zero, click on the "new pole" or "new zero" button. The new root will appear at (0,0) and then you can drag it to the desired location. To remove a root, click on it and then click on the "delete p/z" button. You can undo the delete operation by right clicking on the "delete p/z" button. (This is a multi-level undo, so you can delete all the roots and then restore them all by continuing to right click on the button.) Click on the "save" button to save the current transfer function. (It will be stored in a file called editz.mat in the same folder as editz.m.) Click the "load" button to restore the transfer function stored in the file. When you start editz, the initial transfer function will be loaded from this file. If you want to start editz using the default transfer function mentioned above, simply delete the editz.mat file.

The coefficient strip

The dark blue strip between the two plots shows the coefficients of the transfer function numerator and denominator polynomials (num(z) and den(z)). The highest-order term is on the left. You will see these coefficients change whenever you move roots around using the pole/zero plot, add or remove roots, or hit one of the quantization buttons. You can also edit these coefficients by typing in new values. Just right click on any coefficient, backspace to remove the old value and type in a new value. When you press "enter", the new value will be accepted and the transfer function and pole/zero plots will be updated to reflect the new transfer function. You can also increase or decrease the coefficient value by a small amount (.001 by default) by left clicking on it. If you click closer to the right edge of the number, the coefficient will increase and if you click closer to the left edge it will decrease. It's also interesting to hold down the mouse button while the mouse is over a coefficient. What will happen then is that the coefficient will slowly increase or decrease, while you watch the roots move slowly in the lower plot, and the magnitude and phase response changes in the upper plot. (You can adjust the update rate if you like.) The text color for the coefficients alternates between purple and yellow every 5 values. (i.e. the first 5 are purple, the next 5 are yellow, then back to purple, etc.) This makes it easier to see at a glance how many coefficients there are. There is only enough room to display the first 12 coefficients of each polynomial with the default figure size, but if you add enough roots to go beyond that you can stretch the figure width if you need to see all the coefficients.

Quantization

While (or after) you are dragging a root of the transfer function in the pole/zero plot, the associated polynomial is saved in its full precision (i.e. 64-bit floating point). Although only 5 decimal places are displayed in the coefficient strip, the full precision is available in the base workspace variables as well as in the editz.mat file if the save button is pressed. However, suppose we then click on the "den quant: 100" with the mouse. (It doesn't matter whether you click on the number or the label.) Then all the coefficients in the denominator polynomial will be rounded to two digits after the decimal point. (i.e. a coefficient value of 1.6388 would be rounded to 1.64). But that's only the default quantization. Suppose for example that you wanted to round the denominator coefficients to 4 digits after the decimal point. To do this, right click on "den quant: 100" (either the number or the label), then backspace to remove the "100" and then enter "10^4". Or suppose you want to round to 6 binary digits after the binary point. Then you would enter "2^6". This quantization feature has been included in editz because when a digital filter is realized the filter coefficients will become quantized to a level that depends on the implementation. So it is useful to get a feel for how this quantization affects the root locations and the frequency response.

As mentioned in the previous section, when you click on one of the coefficients in the coefficient strip, that coefficient will increase or decrease by .001. But that is only the default. Suppose you want the coefficients to change by .0001 instead. To do that, left or right click on the "num incr: 1000" or "den incr: 1000" string, backspace and enter "10^4". Or enter something like "2^4" to cause the increment/decrement operation to change the values by 1/16. Instead of incrementing by a fixed amount, you can also choose to increment by a fixed percentage. A negative entry indicates this. For example, if you want the denominator coefficients to increment/decrement by 0.1% every time you click on them, then click on the "den incr: 1000" string and enter "-0.1".

It is sometimes desirable to keep the numerator polynomial symmetric (i.e. it reads the same left to right or right to left). This keeps all the zeros on the unit circle or in pairs at distances r and 1/r. To ensure that the numerator remains symmetric as you increment or decrement a numerator coefficient, put a check in the "Symmetric" check box. (Even with this checked, you can still end up with an unsymmetrical numerator by dragging a zero off the unit circle in the pole/zero plot.) With the coefficient strip example above, with Symmetric checked, modifying the 2nd numerator coefficient (4.3) will also modify the 5th coefficient and visa versa. Try continuously decreasing the value starting from 4.3 by holding the mouse button down near the left edge of either the 2nd or the 5th coefficient. As you do this notice that two of the zeros on the unit circle move towards each other, then collide and split apart in a radial direction towards and away from the origin. (This will be a familiar behavior if you have studied root locus analysis.) Note that the symmetry checkbox does not affect the denominator polynomial since there is no particular advantage to a symmetric denominator.

At the bottom of this group is the "DC gain" readout which shows the value that the step response will eventually settle to. It is computed by adding up all the numerator coefficients and dividing that result by the sum of the denominator coefficients. This readout is always up to date since it is changes even while you are dragging a root on the pole/zero plot.

Base workspace variables

The current numerator and denominator polynomials are copied to the base workspace using the variable names pn and pd respectively. This allows you to type commands at the command prompt to do further analysis or editing of the current filter. For example, you could display the step response by typing this into the command window:

in = ones(1,40);
step = filter(pn,pd,in);
plt(step);


Or to produce a step response using vertical bars, replace the last line with this slightly more complex plt command:

plt(Pvbar(in,0,step),
 'title','step response');


Or you could plot the group delay with a command such as this:

plt((0:511)/1024,grpdelay(pn,pd),'title','group delay');

Note that this command will only work if you have the signal processing toolbox since the grpdelay function is defined in that toolbox.

Although you could compute the zeros and poles from the numerator and denominator polynomials for convenience they are also copied to the base workspace using the variable names z and p respectively. (Only the roots in the upper half plane are included.) Here is an example of using the z workspace variable:

Although editz provides a way to quantize the polynomial coefficients it doesn't provide a way to quantize root locations. Suppose after editing the numerator polynomial in the coefficient strip you wanted to move the zeros to the nearest multiple of 5 degrees. Running the following script from the command window would perform that function:
plt xleft EDIT 5;                            % exit data editing mode
[t r] = cart2pol(real(z),imag(z));           % convert zeros to polar (theta,rho)
c = 36/pi; [x y] = pol2cart(round(c*t)/c,r); % round angle to nearest 5 degrees
h = getappdata(gcf,'Lhandles');              % list of lines [Mag Phase Zeros Poles Circle]
set(h(3),'x',x,'y',y);                       % save quantized data to the zeros line
a = get(gcf,'ResizeFcn'); feval(a{1});       % update the frequency response plot
Note that the z workspace variable is used to retrieve the current zero locations but it is not sufficient to merely modify that variable. You actually have to modify the line data so that the plot gets updated. Also without the last line, the frequency response plot would not reflect the new locations of the zeros.

Help

Clicking on the "Help" tag in the menu box to the left of the pole/zero plot will bring up the document you are currently reading. Notice that in the navigation pane on the left, you can navigate to the plt help content. (plt is the plotting tool used by editz). Of particular importance is the section "Using the plt window" which will help you get the most from using this application. If you are interested in creating new commands similar to the ones described above for step response and group delay, you may also want to look at the section "Programming with plt".

After using editz for a while, most people guess that an application like this would involve thousands of lines of code. So you may be surprised to learn that editz.m consists of less than 200 lines of code. The main reason the code is so small is that the plt toolbox includes many features needed to create complex plotting-based graphical interfaces.

If your questions are not answered by reading the help documentation, don't hesitate to contact the author. My email address appears at the top of this document and can also be found at the top of any of the included .m files.

Copyright © 2023
Paul Mennen