N = 6 scaling functions and mother wavelets

introduction

The impetus for this post is figure 1.4 on page 6 of Burrus et al. (Since it’s been a while, that’s Burrus, C. Sidney; Gopinath, Ramesh A.; Guo, Haitao. Introduction to Wavelets and Wavelet Transforms, A Primer. Prentice Hall, 1998.ISBN 0 13 489600 9.)

They offered the figure as an illustration of four different scaling functions; in addition, these scaling functions were parameterized by two angles.

Now I know how to produce the drawings of those scaling functions — and I also know how to produce drawings of the corresponding mother wavelets, which they did not show on page 6. It also turns out that they have interchanged the legends for figures (a) and (b) — and when we can produce the drawings ourselves, that mistake becomes almost irrelevant.

This post also serves to reiterate the calculation sequence for plotting a scaling function and its corresponding mother wavelet.

setup

It turns out that there are equations which must be satisfied by any “reasonable” filter coefficients h. I expect to show these to you in the next post. I have already shown you a description of these solutions of these equations when we have 4 nonzero coefficients. And I have shown you how to compute scaling functions and mother wavelets for N = 4 (D4 only) and for N = 2 (D2 = Haar).

Let me emphasize that what I understand is how to get the equations which the filter coefficients h must satisfy. What I do not yet understand is how to parameterize the solutions in terms of angles.

Let me now hand you a description of the solutions when we have 6 nonzero coefficients. The four examples I am about to work out all come from specific choices of these solutions. That is, for every one of the following examples, N = 6.

The following 4 scaling functions match figure 1.4, although (a) and (b) are swapped. (The legend describes the values “a” and “b” in the equations; the legend for figure a belongs with figure b.)

In addition, they have drawings of the Daubechies D6 (p. 82) and Coiflet C6 (p. 94) mother wavelets, so I have confirmed 6 of the following 8 graphs.

From p. 66 of Burrus et al., we get the following (using H instead of h just because it lets me preserve the equations in H while setting values for h.)

Let me tell you before I start writing that the last two equations are actually

H(4) = -H(0)-H(2)+\frac{1}{\sqrt{2}}

H(5) = -H(1)-H(3)+\frac{1}{\sqrt{2}}

That is, they say that the sum of the even coefficients is equal to the sum of the odd coefficients is equal to half the sum of all the coefficients = \frac{1}{2} \sqrt{2}= \frac{1}{\sqrt{2}}\ . They will look much more complicated than that when I substitute the first four equations.

H(0) = \frac{(\cos (a)+\sin (a)+1) (-\cos (b)-\sin (b)+1)+2 \cos (a) \sin (b)}{4 \sqrt{2}}

H(1) = \frac{(-\cos (a)+\sin (a)+1) (\cos (b)-\sin (b)+1)-2 \cos (a) \sin (b)}{4 \sqrt{2}}

H(2) = \frac{\cos (a-b)+\sin (a-b)+1}{2 \sqrt{2}}

H(3) = \frac{\cos (a-b)-\sin (a-b)+1}{2 \sqrt{2}}

H(4) = -\frac{\cos (a-b)+\sin (a-b)+1}{2 \sqrt{2}}-\frac{(\cos (a)+\sin (a)+1) (-\cos (b)-\sin (b)+1)+2 \cos (a)   \sin (b)}{4 \sqrt{2}}+\frac{1}{\sqrt{2}}

H(5) = -\frac{\cos (a-b)-\sin (a-b)+1}{2 \sqrt{2}}-\frac{(-\cos (a)+\sin (a)+1) (\cos (b)-\sin (b)+1)-2 \cos (a)   \sin (b)}{4 \sqrt{2}}+\frac{1}{\sqrt{2}}

legend 1.14 a (figure b)

The first choice (the legend for figure 1.14 a) for the angles a and b (in radians) is

\{a\to 1.3598,b\to -0.782106\}

(I knew when I saw those that the figure was wrong; by that time I recognized the D6 h’s.)

The resulting h’s are…

\{0.332671,0.806892,0.459878,-0.135011,-0.0854413,0.0352263\}

Now we form the m0 matrix (in stages for clarity)…

 \left(\begin{array}{llllll} \text{h0} & 0 & 0 & 0 & 0 & 0 \\ \text{h2} & \text{h1} & \text{h0} & 0 & 0 & 0 \\ \text{h4} & \text{h3} & \text{h2} & \text{h1} & \text{h0} & 0 \\ 0 & \text{h5} & \text{h4} & \text{h3} & \text{h2} & \text{h1} \\ 0 & 0 & 0 & \text{h5} & \text{h4} & \text{h3} \\ 0 & 0 & 0 & 0 & 0 & \text{h5}\end{array}\right)

Then we multiply by Sqrt[2]…

M_0 = \left(\begin{array}{llllll} \sqrt{2}\ \text{h0} & 0 & 0 & 0 & 0 & 0 \\ \sqrt{2}\ \text{h2} & \sqrt{2}\ \text{h1} & \sqrt{2}\ \text{h0} & 0 & 0 & 0   \\ \sqrt{2}\ \text{h4} & \sqrt{2}\ \text{h3} & \sqrt{2}\ \text{h2} & \sqrt{2}\   \text{h1} & \sqrt{2}\ \text{h0} & 0 \\ 0 & \sqrt{2}\ \text{h5} & \sqrt{2}\ \text{h4} & \sqrt{2}\ \text{h3} &   \sqrt{2}\ \text{h2} & \sqrt{2}\ \text{h1} \\ 0 & 0 & 0 & \sqrt{2}\ \text{h5} & \sqrt{2}\ \text{h4} & \sqrt{2}\ \text{h3}   \\ 0 & 0 & 0 & 0 & 0 & \sqrt{2}\ \text{h5}\end{array}\right)

Note that since all 4 examples have N = 6, that is the m0 matrix in principle for each of these examples. I won’t show it again.

Now we set the values…
M_0 = \left(\begin{array}{llllll} 0.470467 & 0. & 0. & 0. & 0. & 0. \\ 0.650365 & 1.14112 & 0.470467 & 0. & 0. & 0. \\ -0.120832 & -0.190934 & 0.650365 & 1.14112 & 0.470467 & 0. \\ 0. & 0.0498175 & -0.120832 & -0.190934 & 0.650365 & 1.14112 \\ 0. & 0. & 0. & 0.0498175 & -0.120832 & -0.190934 \\ 0. & 0. & 0. & 0. & 0. & 0.0498175\end{array}\right)

We find the eigenvector of eigenvalue 1. Mathematica returned a unit vector, but I want one whose components add up to 1. I will simply divide the unit vector by the sum of its components.

Here’s the unit vector…

\{0.,-0.955434,0.286583,-0.0707606,-0.00314509,0.\}

The sum of its components is -0.742756, so I get

V = \{0.,1.28634,-0.385837,0.0952675,0.00423435,0.\}

This function should be defined on [0,5]. I use that vector for the values of the scaling function at the integers.

Picture 34

Working, I graphed this immediately, but for the post, I ought to put the two drawings — scaling function and mother wavelet — in close proximity. This one turns out to be the Daubechies D6 scaling function.

To get the D6 mother wavelet, we take our filter coefficients h…

h = \{0.332671,0.806892,0.459878,-0.135011,-0.0854413,0.0352263\}

… we reverse them, and alternate the signs. The resulting filter coefficients are often denoted by h1 or by g. I’ll use g. The resulting g coefficients are what I expect (the sign of g[0] = h[5] has not been changed), but their Table 6.2 on p. 79 has the negatives of these numbers. And yet, I match their picture on p. 82.

(That’s why there’s a \pm in front of the recipe. Sorry, but you’ll have to look for it in the post.)

g = \{0.0352263,0.0854413,-0.135011,-0.459878,0.806892,-0.332671\}

Define the mother wavelet…

Picture 35

and plot it…
(These are Daubechies D6 mother wavelet and scaling function, respectively.)

Picture 36

Beautiful. That matches their picture on p. 82.

And here’s the D6 scaling function whose plot I delayed showing you…

Picture 37

and that matches (b), rather than (a), of figure 1.4.

legend 1.14 b (figure a)

Let’s make a different choice for a and b. I believe this is the “Coiflet” of order 6.

\{a\to 1.1468,b\to 0.42403\}

The resulting h’s are:

h = \{-0.0727362,0.337915,0.852573,0.384847,-0.0727302,-0.0156552\}

Now we form the m0 matrix exactly as before, and set the new values…

 M_0 = \left(\begin{array}{llllll} -0.102864 & 0. & 0. & 0. & 0. & 0. \\ 1.20572 & 0.477884 & -0.102864 & 0. & 0. & 0. \\ -0.102856 & 0.544256 & 1.20572 & 0.477884 & -0.102864 & 0. \\ 0. & -0.0221398 & -0.102856 & 0.544256 & 1.20572 & 0.477884 \\ 0. & 0. & 0. & -0.0221398 & -0.102856 & 0.544256 \\ 0. & 0. & 0. & 0. & 0. & -0.0221398\end{array}\right)

We find the eigenvector of eigenvalue 1.

\{0.,-0.189494,0.961829,-0.197385,0.00396248,0.\}

That’s orthonormal, so I find the sum of its components (0.578913) and divide by it, getting

V = \{0.,-0.327328,1.66144,-0.340958,0.0068447,0.\}

Set those to be the values of the scaling function at the integers, and define the recursion…

Picture 38

Again, I will delay the plot until I have the mother wavelet.

To get the mother wavelet, we start with the h’s…

h = \{-0.0727362,0.337915,0.852573,0.384847,-0.0727302,-0.0156552\}

(Those agree with p 92)

We reverse them, and alternate the signs. (This time, I need to use their signs! And they have got g[0] = -h[5].)

 g = \{0.0156552,-0.0727302,-0.384847,0.852573,-0.337915,-0.0727362\}

Picture 39

compute and plot…
(These are the Coiflet C6 mother wavelet and scaling function in order.)

Picture 40

That matches their p. 94 drawing of the C6 mother wavelet.

And here’s the C6 scaling function…

Picture 41

and that matches their figure 1.14 (a).

figure 14.1 c

I do not know if the following pair has a name. We take

\left\{a\to \frac{23 \pi }{60},b\to -\frac{\pi }{12}\right\}

The resulting h’s are…

h = \{0.0858766,0.652297,0.742126,0.0388932,-0.120896,0.0159163\}

Now we form the m0 matrix, and set the values.

 M_0 = \left(\begin{array}{llllll} 0.121448 & 0. & 0. & 0. & 0. & 0. \\ 1.04953 & 0.922488 & 0.121448 & 0. & 0. & 0. \\ -0.170973 & 0.0550033 & 1.04953 & 0.922488 & 0.121448 & 0. \\ 0. & 0.022509 & -0.170973 & 0.0550033 & 1.04953 & 0.922488 \\ 0. & 0. & 0. & 0.022509 & -0.170973 & 0.0550033 \\ 0. & 0. & 0. & 0. & 0. & 0.022509\end{array}\right)

Now we find the eigenvector of eigenvalue 1:

\{0.,-0.840331,-0.536329,0.0786992,0.00151279,0.\}

The sum of its components is -1.29645, so we divide by it, to get a vector whose components add up to 1:

V = \{0.,0.648179,0.413691,-0.0607037,-0.00116688,0.\}

That gives us the initial values, and we define the recursion…

Picture 42

Recall the h’s…

h =\{0.0858766,0.652297,0.742126,0.0388932,-0.120896,0.0159163\}

We reverse them, and alternate the signs.

g = \{-0.0159163,-0.120896,-0.0388932,0.742126,-0.652297,0.0858766\}

Redefine the mother wavelet…

Picture 43

and plot it…

Picture 44

… followed by the scaling function:

Picture 45

The last case for their Figure 1.4.

Here are the angles a and b…

\left\{a\to \frac{3 \pi }{4},b\to \frac{2 \pi }{15}\right\}

Here are the resulting h’s…

h = \{-0.158303,0.744755,0.556922,-0.103219,0.308488,0.0655711\}

We form the M0 matrix and set its values…

M_0 = \left(\begin{array}{llllll} -0.223874 & 0. & 0. & 0. & 0. & 0. \\ 0.787606 & 1.05324 & -0.223874 & 0. & 0. & 0. \\ 0.436267 & -0.145974 & 0.787606 & 1.05324 & -0.223874 & 0. \\ 0. & 0.0927315 & 0.436267 & -0.145974 & 0.787606 & 1.05324 \\ 0. & 0. & 0. & 0.0927315 & 0.436267 & -0.145974 \\ 0. & 0. & 0. & 0. & 0. & 0.0927315\end{array}\right)

Once again we find the eigenvector of eigenvalue 1. (If you’re using Mathematica, be careful. It’s probably the 2nd one rather than the 1st, in this case.) The normalized eigenvector is…

\{0.,0.955662,0.22728,0.184742,0.0303893,0.\}

The sum of its components is 1.39807, so we divide through and get our initial values for the scaling function…

V = \{0.,0.683556,0.162567,0.13214,0.0217365,0.\}

So we define the scaling function

Picture 46

Here are the h’s…

h = \{-0.158303,0.744755,0.556922,-0.103219,0.308488,0.0655711\}

We reverse them, and alternate the signs to get a set of g’s…

g = \{-0.0655711,0.308488,0.103219,0.556922,-0.744755,-0.158303\}

Define the mother wavelet…

Picture 47

Compute and plot it…

Picture 48

And here’s the scaling function (which we defined first, as usual)…

Picture 49

Closing

So. We’ve had some practice computing the scaling function and the mother wavelet from the h’s. We know that the h’s are not arbitrary, but are given by solutions to some set of equations, and I’ve shown you the general solutions for N = 4 and N = 6.

Now I really owe you an explanation of where the heck these computations come from. But at least you’ll know why I’m writing equations when you see them.

Next, I think.

Mother wavelet from scaling function: D4 and Haar

D4 dyadic wavelet

We can compute the mother wavelet from the scaling function. Let me show you how to do this for Daubechies’s D4.

First, we need the scaling function.

the D4 scaling function again, quickly

This is review. There is a matrix M0 which has an eigenvector with eigenvalue 1, and that eigenvector gives me the values of the scaling function \varphi at the integers. Once I have initial values, I can compute \varphi by recursion (and because of the specific form of the recursion, only at points whose denominator is a power of 2).

I start by constructing the matrix M0 in principle…

M_0 = \left(\begin{array}{llll} \sqrt{2}\  \text{h0} & 0 & 0 & 0 \\ \sqrt{2}\  \text{h2} & \sqrt{2}\  \text{h1} & \sqrt{2}\  \text{h0}   & 0 \\ 0 & \sqrt{2}\  \text{h3} & \sqrt{2}\  \text{h2} & \sqrt{2}\    \text{h1} \\ 0 & 0 & 0 & \sqrt{2}\  \text{h3}\end{array}\right)

(This comes from evaluating the dilation equation at the integers, then writing the resulting system of equations as a matrix-vector equation. It turns out to be M_0\ \varphi = \varphi\ . In fact, I construct M0 from its pattern, but i know how to derive – hence check – it.)

Then I set the values of the filter coefficients h…

\left\{\text{h0}\to \frac{1+\sqrt{3}}{4 \sqrt{2}\ },\text{h1}\to   \frac{3+\sqrt{3}}{4 \sqrt{2}\ },\text{h2}\to   \frac{3-\sqrt{3}}{4 \sqrt{2}\ },\text{h3}\to   \frac{1-\sqrt{3}}{4 \sqrt{2}\ }\right\}

The matrix M0 becomes…

M_0 = \left(\begin{array}{llll} 0.683013 & 0. & 0. & 0. \\ 0.316987 & 1.18301 & 0.683013 & 0. \\ 0. & -0.183013 & 0.316987 & 1.18301 \\ 0. & 0. & 0. & -0.183013\end{array}\right)

Now I look for an eigenvector having eigenvalue 1. Here are the eigenvalues (first row) and eigenvectors (subsequent rows)…

\begin{array}{c} \{1.,0.683013,0.5,-0.183013\} \\ \left(\begin{array}{llll} 0. & -0.965926 & 0.258819 & 0. \\ 0.408248 & -0.816497 & 0.408248 & 0. \\ 0. & 0.707107 & -0.707107 & 0. \\ 0. & 0.408248 & -0.816497 & 0.408248\end{array}\right)\end{array}

We see, as we saw before, that we want the first eigenvector from that list. Mathematica has given me a vector of length 1; I want a vector – I’ll explain later – whose components sum to 1.

V = \{0.,1.36603,-0.366025,0.\}

I take those components as the initial values of the scaling function, i.e. its values at the integers. Then I write a recursive function definition, which includes the requirement that the function is zero outside the interval [0,3].

Frankly, the easiest way to show it to you is a drawing, especially of what Mathematica knows after I make the definition; read the last line.

D4 may 9 1

In order to make a point, I am not going to evaluate that function anywhere else. I have all I need for now.

the D4 mother wavelet

Let me hand you another recipe. The “mother wavelet” \psi satisfies an equation very much like the dilation equation. We have

\psi(t) = \sum_{n}{g(n)\ \sqrt{2}\ \ \varphi(2\ t - n)}

We do not have to specify that the function is zero outside [0,3]; all we have to do is feed it \varphi\ .

It’s important that it is not a recursion for \psi\ : the LHS is \psi(t) but the RHS is still the scaling function \varphi(2t-n)\ . And the coefficients have changed. They are often denoted by h1 or by g. I think I’ll use g.

The g(n) are related to the h(n), but not uniquely. In general,

g(n) = \pm (-1)^n\ h(L-1-n)\ , for L an even integer (I’m pretty sure it has to be even).

An extremely convenient choice is L = N, the number of nonzero h’s, in which case we get

g(n) = \pm (-1)^n\ h(N-1-n)\ ,

which simply says reverse the h’s and alternate the signs.

That is, for our case, N = 4, so we’re looking at h(3-n), and then

g(0) = h(3)
g(1) = -h(2)
g(2) = h(1)
g(3) = -h(0)

(or the negative of all those).

Here are our h’s again…

\left\{\frac{1+\sqrt{3}}{4 \sqrt{2}\ },\frac{3+\sqrt{3}}{4   \sqrt{2}\ },\frac{3-\sqrt{3}}{4 \sqrt{2}\ },\frac{1-\sqrt{3}}{4   \sqrt{2}\ }\right\}

or

\{0.482963,0.836516,0.224144,-0.12941\}

We reverse them, and alternate the signs, in order to get the g’s.

\left\{\frac{1-\sqrt{3}}{4 \sqrt{2}\ },-\frac{3-\sqrt{3}}{4   \sqrt{2}\ },\frac{3+\sqrt{3}}{4   \sqrt{2}\ },-\frac{1+\sqrt{3}}{4 \sqrt{2}\ }\right\}

or

\{-0.12941,-0.224144,0.836516,-0.482963\}

Oddly enough, Burrus et al. showed the opposite of those signs. That doesn’t agree with their own equation, and it would lead to the negative of the following graph – but my picture matches their picture!

Now we define \psi in terms of \varphi(2t-n)\

D4 may 9 2

It’s time to just plot the D4 mother wavelet.

D4 may 9 3

and that looks good.

NOTE that it will compute whatever it needs of \varphi\ , so in a sense it is recursive. This is the point I wanted to make: I did not have to compute \varphi for it, it could do it itself.

Just to put them near each other, here’s a picture of the scaling function:

D4 may 9 4

the Haar wavelet system

Let me show you all of that again for a much simpler case. The Haar wavelets, as they are now called, was invented long before we knew they was a wavelet system. Its scaling function is a step function, defined to be 1 on the half open interval [1,0) and zero elsewhere. I will eventually show you – I hope – that it could be considered the D2 scaling function also.

Oh, here I go again using a cannon when a slingshot would more than suffice. There is no reason to use recursion to graph this scaling function, nor even to graph this mother wavelet. But it’s nice to know that the algorithm works in the simplest case.

Haar (D2) scaling function

We start with the M0 matrix in principle, for two nonzero h’s…

M_0 = \left(\begin{array}{ll} \sqrt{2}\  \text{h0} & 0 \\ 0 & \sqrt{2}\  \text{h1}\end{array}\right)

I simply tell you that the h’s have these (two identical) values…

\left\{\text{h0}\to \frac{1}{\sqrt{2}\ },\text{h1}\to   \frac{1}{\sqrt{2}\ }\right\}

Then the matrix M0 is…

M_0 = \left(\begin{array}{ll} 1. & 0. \\ 0. & 1.\end{array}\right)

Well, well. By inspection – it’s diagonal! – there are two eigenvalues equal to 1, and the eigenvectors are the columns of that matrix. We might as well choose the eigenvector

V = \{1,0\}

The sum of the components is already 1, so we don’t need to scale it to get the initial values of the scaling function.

We define the scaling function \varphi as usual…

D4 may 9 5

Let’s plot it.

D4 may 9 6

A unit step function on the half-open unit interval. I’m rather pleased to see that.

D2 wavelet

To get the g’s for the mother wavelet, we reverse the h’s (oh, they’re the same!) and alternate the signs…

\left\{\frac{1}{\sqrt{2}\ },-\frac{1}{\sqrt{2}\ }\right\}

We write the definition… ask what we know… and then we plot the mother wavelet…

D4 may 9 7

Yes! That’s exactly what I wanted to see. And if you’ve ever seen the Haar (D2) mother wavelet, it’s what you wanted to see, too.

I think the next post will show you a few more scaling functions and mother wavelets, for six nonzero h’s.

The dyadic expansion of Daubechies D4 scaling function

introduction

edit jun 13: corrected one of the 4 equations at the end.

I have shown you one way to compute the D4 scaling function. I am not entirely comfortable with the method, but I don’t need to be: I can do better.

The method I’ve shown you begins with a terrible approximation — a constant function or signal — and improves it by repeatedly applying a fixed filter to it.

The primer by Burrus et al. also provides MATLAB® code for a quite different method. It turns out that we can find the exact values of the D4 scaling function at the integers. The dilation equation can then be used to find the exact values at the halves… then the exact values at the quarters… and so on. It’s called a dyadic expansion because it works for points whose denominator is a power of 2.

Their code, however, was challenging to figure out.

But I don’t need to figure it out. I can do better.

I can do so much better that it must be illegal, immoral, and fattening.

I don’t have to write any code at all — well, ok, I have to write an “If” clause. Mathematica® can do recursion, and the dilation equation is all I need. Oh, I need initial values, too.

Rather than distract you from this marvel by putting the details first, I’m going to show you the end product first.

the dyadic expansion simply & efficiently

To do a recursion, I need to have initial values. I’ll derive them later in this post, but the values of the scaling function at the integers 0, 1, 2, 3 are components of an eigenvector V:

V = \{0.,1.36603,-0.366025,0.\}

I set those to be the function values at 4 points…

\{\varphi (0),\varphi (1),\varphi (2),\varphi (3)\} = V

and then I define the function. (Whoa! I have to use a picture, apparently, because of special characters.)

Picture 45

(Actually, I can make that work. The problem is the < and > symbols, which are apparently being interpreted as containing nonsense HTML. Use & lt; and & gt; without the space after the “&”, which is what I did to make the code display.

\varphi[t\_]:=\varphi[t]=\text{If}\left[t <0 || t >3,0,\text{Chop}\left[\sum _{n=0}^3 h(n) \sqrt{2} \varphi (2\ t-n)\right]\right]

The set delayed operator (:=) says don’t do anything until I give it an actual input. The \varphi[t] in the section \varphi[t\_] := \varphi[t]= just says “after you compute it, assign it”.

There is a way to see what Mathematica® knows at this point.

?? \varphi

picture-341

Let’s compute it at 1/2. We get

\varphi[1/2] = 0.933013

and let’s see what Mathematica® knows now:

picture-361

He knows a lot, more than when he started. And he will return from the table as soon as he finds any known value, and fall thru to the last line — the recursion — only for unknown values. This is a combined lookup table and recursion.

(I know that both Java and C++ are recursive; it appears that MATLAB® is not.)

Now that is nice. It shows that Mathematica® needed a wide range of values for the computation, and it saved them — and, more importantly, the next time it needs, for example, \varphi[1/2]\ , it will find it in that list before it gets to the final entry, which is the recursion.

I must emphasize that we are computing \varphi exactly, at new points. The values at old points are never changed in this process.

OK, let’s see what we get. There’s absolutely no computational reason to proceed in stages, but I want to make sure you see it grow.

Here I show the initial values (\varphi at the integers)…
picture-37

We add the values at the halves.

picture-38

We add the values at the quarters. And I can disdainfully tell it to “recompute” the values at the halves because I know it will look them up rather than actually compute them.

picture-39

Add the eighths…

picture-40

Sixteenths…

picture-41

Thirty-seconds…

picture-42

Sixty-fourths…

picture-43

One-twenty-eighths…

picture-44
I note, from the position of the dots to the right of the maximum, that the function is changing very rapidly there. I wouldn’t be surprised if the convergence in our previous method is not very quick there.

getting the initial values

Let me now back up and show you how I got the scaling function \varphi at the integers. Oh, understand that it is zero outside the interval [0,3].

Here is the dilation equation for N=4, that is, for four nonzero filter coefficients h.

\varphi (t)=\sqrt{2} h(0) \varphi (2 t)+\sqrt{2} h(3) \varphi (2 t-3)+\sqrt{2} h(2) \varphi   (2 t-2)+\sqrt{2} h(1) \varphi (2 t-1)

First, evaluate the dilation equation at the integers 0 .. 4. If we simply set t = 0, we get

\varphi (0)=\sqrt{2} h(3) \varphi (-3)+\sqrt{2} h(2) \varphi (-2)+\sqrt{2} h(1) \varphi   (-1)+\sqrt{2} h(0) \varphi (0)

but then we need to zero out the three values of \varphi at the negative integers in that equation, getting

\varphi (0)=\sqrt{2} h(0) \varphi (0)

For t = 1,

\varphi (1)=\sqrt{2} h(3) \varphi (-1)+\sqrt{2} h(2) \varphi (0)+\sqrt{2} h(1) \varphi   (1)+\sqrt{2} h(0) \varphi (2)

and this time we set \varphi[-1] = 0, getting

\varphi (1)=\sqrt{2} h(2) \varphi (0)+\sqrt{2} h(1) \varphi (1)+\sqrt{2} h(0) \varphi (2)

For t = 2…

\varphi (2)=\sqrt{2} h(3) \varphi (1)+\sqrt{2} h(2) \varphi (2)+\sqrt{2} h(1) \varphi   (3)+\sqrt{2} h(0) \varphi (4)

and we set \varphi[4] = 0\ , getting…

\varphi (2)=\sqrt{2} h(3) \varphi (1)+\sqrt{2} h(2) \varphi (2)+\sqrt{2} h(1) \varphi (3)

finally, t = 3…

\varphi (3)=\sqrt{2} h(3) \varphi (3)+\sqrt{2} h(2) \varphi (4)+\sqrt{2} h(1) \varphi   (5)+\sqrt{2} h(0) \varphi (6)

and we set three of the \varphi to zero, getting

\varphi (3)=\sqrt{2} h(3) \varphi (3)

so, we have the system of equations

 \begin{array}{c} \varphi (0)=\sqrt{2} h(0) \varphi (0) \\ \varphi (1)=\sqrt{2} h(2) \varphi (0)+\sqrt{2} h(1) \varphi (1)+\sqrt{2} h(0) \varphi (2)   \\ \varphi (2)=\sqrt{2} h(3) \varphi (1)+\sqrt{2} h(2) \varphi (2)+\sqrt{2} h(1) \varphi (3)   \\ \varphi (3)=\sqrt{2} h(3) \varphi (3)\end{array}

and we could solve them.

It is more instructive and useful to look at a matrix representation. That set of equations can be written

M_0 \varphi = \varphi

with the matrix M0 defined — in stages — as

\left(\begin{array}{llll} \text{h0} & 0 & 0 & 0 \\ \text{h2} & \text{h1} & \text{h0} & 0 \\ 0 & \text{h3} & \text{h2} & \text{h1} \\ 0 & 0 & 0 & \text{h3}\end{array}\right)

and then I multiply it by \sqrt{2}\ , getting

\left(\begin{array}{llll} \sqrt{2} \text{h0} & 0 & 0 & 0 \\ \sqrt{2} \text{h2} & \sqrt{2} \text{h1} & \sqrt{2} \text{h0} & 0 \\ 0 & \sqrt{2} \text{h3} & \sqrt{2} \text{h2} & \sqrt{2} \text{h1} \\ 0 & 0 & 0 & \sqrt{2} \text{h3}\end{array}\right)

(I created M0 using the diagonal bands, long before I knew how it was derived. Things were a little clearer to me without that ubiquitous \sqrt{2}\ .

Oh, and the vector \varphi holds the 4 values of \varphi at 0, 1, 2, 3:

\begin{array}{c} \varphi (0) \\ \varphi (1) \\ \varphi (2) \\ \varphi (3)\end{array}

But that matrix equation says that \varphi is an eigenvector of M0, with eigenvalue 1. And we can find eigenthings.

To solve it, we need the values of h for the D4 scaling function.

\left\{\text{h0}\to \frac{1+\sqrt{3}}{4 \sqrt{2}},\text{h1}\to \frac{3+\sqrt{3}}{4   \sqrt{2}},\text{h2}\to \frac{3-\sqrt{3}}{4 \sqrt{2}},\text{h3}\to \frac{1-\sqrt{3}}{4 \sqrt{2}}\right\}

For the D4 scaling function, then, M0 becomes

\left(\begin{array}{llll} \frac{1}{4} \left(1+\sqrt{3}\right) & 0 & 0 & 0 \\ \frac{1}{4} \left(3-\sqrt{3}\right) & \frac{1}{4} \left(3+\sqrt{3}\right) & \frac{1}{4}   \left(1+\sqrt{3}\right) & 0 \\ 0 & \frac{1}{4} \left(1-\sqrt{3}\right) & \frac{1}{4} \left(3-\sqrt{3}\right) & \frac{1}{4}   \left(3+\sqrt{3}\right) \\ 0 & 0 & 0 & \frac{1}{4} \left(1-\sqrt{3}\right)\end{array}\right)

or

\left(\begin{array}{llll} 0.683013 & 0. & 0. & 0. \\ 0.316987 & 1.18301 & 0.683013 & 0. \\ 0. & -0.183013 & 0.316987 & 1.18301 \\ 0. & 0. & 0. & -0.183013\end{array}\right)

Here are its eigenvalues (first row), and corresponding eigenvectors…

\begin{array}{c} \{1.,0.683013,0.5,-0.183013\} \\ \left(\begin{array}{llll} 0. & -0.965926 & 0.258819 & 0. \\ 0.408248 & -0.816497 & 0.408248 & 0. \\ 0. & 0.707107 & -0.707107 & 0. \\ 0. & 0.408248 & -0.816497 & 0.408248\end{array}\right)\end{array}

We see that the first eigenvalue is 1, so the first eigenvector is the one we want.

\{0.,-0.965926,0.258819,0.\}

That is a vector of length 1. For reasons we will discuss later, I want a vector whose components add up to 1. It’s still an eigenvector.

\{0.,1.36603,-0.366025,0.\}

(The signs changed because I simply divided by the sum, and the sum was negative.) We take those as the exact values of \varphi at the integers 0 thru 3. You see that \varphi(0) = \varphi(3) = 0\ ,
as I have said before.

So: the initial values of the scaling function are the components of an eigenvector of a matrix M0, specifically of an eigenvector with eigenvalue 1. That is how I got them.

the simple recursion

Of course we’ve already set up a recursion combined with a lookup table. I just want to emphasize the distinction between what I actually do, and the unadorned recursion.

We are ready to write the recursion. It looks almost exactly like the dilation equation…

but instead of “==” I use the “set delayed operator “:=”, and the LHS “t” must become a placeholder “t_” ; and the whole definition must be wrapped in an If-test to set all values to zero outside of [0,3] .

Oh, since I’m starting all over again (don’t want to get two sets of definitions mixed up), I need to set the values of h…

\left\{\frac{1+\sqrt{3}}{4 \sqrt{2}},\frac{3+\sqrt{3}}{4 \sqrt{2}},\frac{3-\sqrt{3}}{4   \sqrt{2}},\frac{1-\sqrt{3}}{4 \sqrt{2}}\right\}

Again, I define the function values exactly as before, at 4 points…

\{\varphi (0),\varphi (1),\varphi (2),\varphi (3)\} = \{0.,1.36603,-0.366025,0.\}

And then I define the recursion:

Picture 46

Again, I can code that now, instead of using a picture.

\varphi[t\_]:=\text{If}\left[t <0 || t >3,0,\text{Chop}\left[\sum _{n=0}^3 h(n) \sqrt{2} \varphi (2\ t-n)\right]\right]

The set delayed operator (:=) says don’t do anything until I give it an actual input. What’s different in this definition is \varphi[t \_] := If... instead of \varphi[t \_] := \varphi[t] = If...\ . There is no assignment statement to \varphi[t] saying that the result of the computation should be saved.

Let’s compute \varphi[1/2] again. We get the same answer, of course:

\varphi[1/2] = 0.933013

and let’s see what Mathematica knows:

picture-35

That’s exactly what we knew before we computed it at 1/2. This is a pure recursion. He recomputes everything every time he needs it.

Simple, but potentially expensive in computer time.

Summary

From the dilation equation and the h coefficients, we can get the values of the scaling function \varphi at the integers. we do this either by directly solving a system of equations, or by recognizing this particular system of equations as an eigenvector problem

M_0 \varphi = \varphi\ .

In either case, if we are at all uncertain what the matrix M0 looks like, we can construct it from the equations.

Note that because the values of \varphi at the integers are the components of an eigenvector, they are only determined to with a scalar multiple. That’s ok, we have a reason for normalizing so that the sum of the values is 1. (That, of course, is different from the sum of the squares of the values = 1.) And even that normalization will only get is to within a sign. If you ever plot a scaling function and get the negative of someone else’s picture, all you need to do is change the signs of the inital values at the integers, i.e. change the sign of the eigenvector.

Having the values of \varphi at the integers, we can get it at the halves, then the quarters, etc.

As I have said before, the purpose of this algorithm is to see what the scaling function looks like, and it will work for the mother wavelet, too.. In practice, however, we can compute the wavelet coefficients of a signal uisng the filter coefficients h (and the corresponding coefficients for the mother wavelet) — we don’t need the values of the scaling function or the wavelet to get the wavelet coefficients.

(I believe that the previous algorithm, however, serves another purpose. It seems more than plausible that the previous algorithm is used to prove existence and uniqueness of the scaling function, once we have its filter coefficients h.)

For comparison with the next case, let me note that the 4 h’s satisfy the following 4 equations…

edit jun 13: the third and fourth equations were identical. i have corrected the third equation by changing the sign of the cosine term.

h(0)=\frac{-\cos (a)+\sin (a)+1}{2 \sqrt{2}}

h(1)=\frac{\cos (a)+\sin (a)+1}{2 \sqrt{2}}

wrong: h(2)=\frac{-\cos (a)-\sin (a)+1}{2 \sqrt{2}}

right: h(2)=\frac{+\cos (a)-\sin (a)+1}{2 \sqrt{2}}

h(3)=\frac{-\cos (a)-\sin (a)+1}{2 \sqrt{2}}

The Daubechies h’s are found by setting a = \pi/3\ .

All I’ve done is push back the mystery of where the h’s came from. Don’t worry. We’ll get there.

I had thought that I would show you plots of other scaling functions, but it makes more sense to show you how to get the mother wavelet.

Next. Unless something really important comes up.

Wavelets: The D4 scaling function

Introduction

I am going to do something a little risky. I’m going to show you how to approximate a particular function – the Daubechies D4 scaling function – even though I am a little shaky on the justification.

If you have ever looked at wavelets, you have probably seen this picture. It is a quintessential “father wavelet” – more commonly, I think, called a “scaling function”.

d4-1-dwg8

I want to compute it; this is not relevant to computing wavelet coefficients, because just as this is computed from its definition, so wavelet coefficients which depend on it and its associated wavelets are computed from its definition rather than from its values.

Talking about this is much like talking about one of one’s favorite movies: what makes something one of my favorite movies is deeply personal, and it doesn’t usually affect my friends that way. To them, at best, it’s just another movie; at worst, they think it is a dud.

I have wanted to know how to compute this function for a long, long time. You have noticed by now, however, that I tend to bounce from one subject to another; my desire to compute this function was put on the back burner.

Let me say again that in practice we do not compute this function: we use its defining characteristics instead of its actual values. But I just had to know how to do it – someday.

Well, it has been “someday” for a little while now; and I’ve been struggling to assemble this post.

It has gotten me to pick up wavelets again, and to look through my books on the subject. This particular computation has gotten me to look at some more challenging Matlab code, and it will lead me to study convolution. (Matlab code would be far less challenging if I had access to Matlab!)

This function is defined on the interval [0, 3]; it has no analytic formula. It is the solution \varphi(t) of a difference equation, called variously “the dilation equation”, “the refinement equation”, and the multi-resolution analysis (MRA) equation”:

\varphi(t) = \sum_n {h(n)\ \sqrt{2}\ \varphi(2\ t - n)}

and in this case, the scaling coefficients h are:

h = \left\{\frac{1+\sqrt{3}}{4\sqrt{2}},\frac{3+\sqrt{3}}{4\sqrt{2}},\frac{3-\sqrt{3}}{4\sqrt{2}},\frac{1-\sqrt{3}}{4 \sqrt{2}}\right\}

It is called D4 because it was invented by Ingred Daubechies and it has 4 nonzero h’s. As I said, it is called a “scaling function” in contrast to “a wavelet”. We’ll see why, down the road.

If we look at wavelets, we see this function very often. But most books do not explicitly show us how to calculate it; and the calculation is not completely straightforward.

The method I am going to use comes out of DSP, discrete signal processing. It is not a tool I use all that comfortably, but the calculation itself is rather simple. On the other hand, details keep piling up, so I am going to split this post.

The method is iterative. We will start with a constant signal, and apply a filter to it eight times. I printed a picture of the transformed signal after each iteration, and I showed it to two friends who had some familiarity with DSP – but who were not practitioners of it.

They both found the algorithm bewildering. I now understand it in general, but there are still details I wonder about. Nevertheless, what I did to my friends was just wave the pictures in their faces, and mutter about upsampling, downsampling, and convolution.

In this post I want to show you the pictures, the Mathematica code, and the underlying idea. In the next post I will fill in some of the underlying details.

Overview

My starting point was Matlab code in the back of a book. If you have Matlab available to you, duplicating my calculations will be very easy – because their code is also available on the Internet.

The very beginning of the appendix containing the code says

“You are free to use these programs or any derivative of them for any scientific purpose but please reference this book. Updated versions of these programs and others can be found on our webpage at: [http://dsp.rice.edu/software/introduction-wavelets-and-wavelet-transforms-primer]“

except I have corrected the URL (replacing dsp-rice by dsp.rice).

The book is: Burrus, C. Sidney; Gopinath, Ramesh A.; Guo, Haitao. Introduction to Wavelets and Wavelet Transforms, A Primer. Prentice Hall, 1998.ISBN 0 13 489600 9.

If you want to see or to use that code, please go get it; while I have used – and will show you – derivative code of my own, I will not actually publish their code. (After all, they said I could use the programs; they didn’t say I could publish them.) Oh, the specific function you want is their “psa(h, kk)”.

They define two completely straightforward functions: downsample and upsample. Here is my Mathematica code for them.

dnsample[x_List] := Table[x[[i]], {i, 1, Length[x], 2}]

upsample[x_List] := Table[{x[[i]], 0}, {i, Length[x]}] // Flatten

The only subtlety in the downsample code is that it drops the even-indexed terms (rather than the odd ones), counting the first term as index 1. Similarly, the upsample code inserts zeroes after the 1st term.

Then they define an upsample function which takes an additional (integer) argument, S, and instead of inserting a single zero between original values, inserts S-1 zeroes. Yes, I do know why their argument was S instead of S-1. You’ll see why, too. Here is my mathematica code for it.

upsample[x_List, S_Integer] :=
Table[{x[[i]], ConstantArray[0, {S - 1}]}, {i, Length[x]}] // Flatten

(Because Mathematica understands parameter lists, I do not have to change the name of the second upsample function; it distinquishes just fine between the function upsample with two arguments and the function upsample with one argument.)

The tricky point for me in the code is the Matlab function “conv”. As far as I can tell, the following Mathematica code is the equivalent.

conv[x_List, y_List] := ListConvolve[x, y, {1, -1}, 0]

(The challenge I face is understanding the options for the ListConvolve command. I would not bet the farm – I might bet a Dover paperback or two – that my Mathematica command is always equivalent to the Matlab command.)

The algorithm

Now let me show you the code that generates the scaling function.

p = dnsample[conv[hu, p]] // N;
Take[%, 384];

The first line computes the convolution of two sequences, hu and p; it downsamples the result; and then it overwrites the sequence p. (The //N converts from rationals to reals.) The second line says that we are only going to plot the first 384 values in p. To rephrase that, this approximation to the scaling function is the first 384 points of the signal p.

(There are other ways to approximate the D4 scaling function; this is the most straightforward – even though I am not all that comfortable with convolution – because it repeatedly applies the same filter, “convolution followed by downsampling”, to an initial constant signal. I had originally thought to look at a different method in this book, until I realized that all I had to understand in this case was one filter.)

What exactly is hu? And where did the 384 come from?

We start with the h coefficients which define the D4 scaling function:

h = \left\{\frac{1+\sqrt{3}}{4\sqrt{2}},\frac{3+\sqrt{3}}{4\sqrt{2}},\frac{3-\sqrt{3}}{4\sqrt{2}},\frac{1-\sqrt{3}}{4 \sqrt{2}}\right\}

We multily by \sqrt{2}\ , and give the result a new name, h2:

h2 = \left\{\frac{1}{4} \left(1+\sqrt{3}\right),\frac{1}{4}\left(3+\sqrt{3}\right),\frac{1}{4}\left(3-\sqrt{3}\right),\frac{1}{4}\left(1-\sqrt{3}\right)\right\}

Why? Recall the dilation equation:

\varphi(t) = \sum_n {h(n)\ \sqrt{2}\ \varphi(2\ t - n)}

All we have done is absorb the \sqrt{2}\ into the h’s. Our dilation equation is now

\varphi(t) = \sum_n {h2(n)\ \varphi(2\ t - n)}

Our function is defined by 4 values of h, and – because of these 4 specific values, I think – our function is nonzero on the interval [0, 3]. We are going to compute it at 128 samples per unit interval, and we have 3 intervals, so we take 384 = 3 * 128 points.

In Mathematica, I used “rules” to set two parameters, K = 3 = 4 – 1, and S = 128, as follows:

ps={K->Length[h2]-1,S->128}

which gives me

\{K\to 3,S\to 128\}

For this post, however, I have chosen to work with these specific numbers; my original Mathematica notebook – in contrast to the notebook for this post – is still “rule based” and I can change the parameters very easily.

Now comes a piece of real magic: we upsample the filter coefficients h2, introducing 127 zeros (and so they wrote the code to do the subtraction for them, 127 = 128 – 1). This we call hu (u for upsampled) and the function call is:

hu=upsample[h2,128];

As a result, the four nonzero values of hu are at indices 1, 129, etc.:

\begin{array}{c} \left\{1,\frac{1}{4} \left(1+\sqrt{3}\right)\right\}  \\ \left\{129,\frac{1}{4}  \left(3+\sqrt{3}\right)\right\} \\ \left\{257,\frac{1}{4}  \left(3-\sqrt{3}\right)\right\} \\ \left\{385,\frac{1}{4}  \left(1-\sqrt{3}\right)\right\}\end{array}

There is one of my first questions: since the final filter coefficient is at index 385, why did they not plot the first 385 values of p?

In any case, hu is an upsampled set of filter coefficients. My friends and I were quite bewildered. We had all heard of upsampling a set of data – but upsampling the filter coefficients instead?

This, it turns out, is quite simple. It also has nothing to do with the up and down sampling characteristic of the filter bank approach to wavelets.

By taking 384 or 385 points, we have changed our timescale from [0, 3] to 1 .. 384 or 1 .. 385. That means we have to move the filter coefficients from the integers 0, 1, 2, 3 to the integers 1, 129, 247, 385 (or possibly to 0, 128, 246, 384, but I choose to start indexing at 1 instead off at 0.)

So much for upsampling the filter coefficients h.

What about the iteration itself? Instead of the dilation equation, the authors write (note the superscripts (k) and (k+1) ):

\varphi^{(k+1)}(t) = \sum_n {h2(n)\ \varphi^{(k)}(2\ t - n)}

This is reminiscent of a fixed point problem

x = f(x)

which we may try to solve as an iteration: guess an x; compute f(x); now call that x because the equations says f(x) is x; if it converges, we have an answer. That is, the iteration:

x^{k+1} = f(x^k)\

might converge. On the other hand, the process might not converge, and even if it does, the answer need not be unique.

We have a slightly different situation because the RHS is at time 2t-n while the LHS is at time t, and it’s the function we’re trying to find, rather than x (or t). Still, if we can find a nice starting function \varphi^{(0)}\ , we can compute \varphi^{(1)}\ , and then \varphi^{(2)}\ , etc.

The idea looks very plausible to me; what threw me for a loop (no pun intended) was digitizing the dilation equation. Understanding that upsampling the filter coefficients was just a change of scale, went a long way toward understanding the algorithm.

I need to show you two things. One is the filter which is applied repeatedly, to get us from \varphi^{(k)}\ to \varphi^{(k+1)}\ . The other is the initialization, \varphi^{(0)}\ .

Here is the initialization step:

picture-19

The first line,

p = ConstantArray[1, {1152}]/9;

says we start with 1152 values of p, each of them equal to 1/9. Let me be clear: I do not know why we choose a power of 2 (2^7= 128) points per unit interval – rather than, say, a power of 2 points for the entire interval [0, 3], nor why we initialzied to 1/9; nor why, with 384 points of interest, we initialized our constant signal to 3 times that length (1152 = 3*384 = 9*128).

The second line,

Take[%, 384];

says that we are only interested in the first 384 points, i.e. we are only interested in the answer over the original range [0,3].

And, as I said before, I don’t know why we look at 384 points instead of 385.

The third line,

data = Transpose[{Range[384]/128, %}];

is used only to change the horizontal scale for plotting purposes: I don’t want a horizontal scale of 1 .. 384, but rather [0,3].

The fourth line is the specific graphics commands and options which I used. Unless you have David Park’s “presentation” package, you will need to use the Mathematica “ListPlot” command instead of “ListDraw”.

dwg[0] = Draw2D[{
Thickness[.01], line, ListDraw[%, Joined -> True]
}, Axes -> True, PlotRange -> {All, {-.5, 1.5}}, Background -> back,
AspectRatio -> 1/GoldenRatio]

Although a plot of the initial function seems superfluous, let me err on the side of too many pictures.

I remind you that I have plotted the first 384 values, but the signal p starts out three times that long.

Okay, let’s apply our filter. Here is a snapshot of my code and the plot:

picture-31

The first line of our code

p = dnsample[conv[hu, p]] // N;

says convolve hu with p, downsample, and replace the signal by that output. The convolution corresponds to the RHS \sum_n {h(n)\ \sqrt{2}\ \varphi(2\ t - n)}\ , and the downsampling should have the effect of setting the result to time t rather than time 2t: \varphi^{(k+1)}(t) rather than \varphi^{(k+1)}(2t)

Once again, the second line of the code,

Take[%, 384];

says take the first 384 values of the sequence p. Note that p itself was redefined in the first line; the second line selects a subset of p, but the next iteration will use more than the 384 points selected on the second line.

The third line, as before,

data = Transpose[{Range[384]/128, %}];

just changes the scale on the horizontal axis. The fourth line, as before,

dwg[1] = Draw2D[{
Thickness[.01], line, ListDraw[%, Joined -> True]
}, Axes -> True, PlotRange -> {All, {-.5, 1.5}}, Background -> back,
AspectRatio -> 1/GoldenRatio]

plots the first 384 values of the current sequence p.

The plots and summary

The initialization, a constant signal = 1/9, \varphi^{(0)}\ :
d4-1-dwg0

After one application (convolve and downsample), \varphi^{(1)}\ :

d4-1-dwg1

After the second application, \varphi^{(2)}\ :

d4-1-dwg2

After the third…

d4-1-dwg3

After the fourth…

d4-1-dwg4

After the fifth…

d4-1-dwg5

After the sixth…

d4-1-dwg6

After the seventh…

d4-1-dwg7

Finally, after the eighth (which is the picture I started this post with)…

d4-1-dwg8

We could worry about how close the answer is, but – as I said – we don’t need this function numerically; what we need in practice is its 4 filter coefficients h.

The summary is simple enough. I am delighted that there is so little overhead involved in this algorithm: convolve and downsample, repeatedly. This is slick and quick.

I do have more details to show you. Soon.