Blogs

The Zeroing Sine Family of Window Functions

Cedron DawgAugust 16, 20202 comments

Introduction

This is an article to hopefully give a better understanding of the Discrete Fourier Transform (DFT) by introducing a class of well behaved window functions that the author believes to be previously unrecognized. The definition and some characteristics are displayed. The heavy math will come in later articles. This is an introduction to the family, and a very special member of it.

This is one of my longer articles. The bulk of the material is in the front half. The back half is mostly example numbers and sample code empty of much explanatory material.

The Work Horse That Started it All

A window function acts like a filter on the DFT values as if they were a signal. The VonHann is one of the simplest, yet most powerful ones. It is equivalent to doing a 0.5( 1, -2, 1 ) filter on the DFT. This is the same as the second difference calculation. What it does is wipe out all "best fit lines" within each three bin set.

This article is available in PDF format for easy printing

A similar "filter" arises naturally out of my frequency formula derivations. It doesn't wipe out the best fit line, but nearly so.

Let $ r = e^{-i\frac{2\pi}{N}} $. Then the definition of the vector is: $$ (-1, 1+r,-r) = r^{1/2} ( -r^{-1/2}, r^{-1/2} +r^{1/2}, -r^{1/2} ) \tag {1} $$ In the formulas, the vector can be multiplied by any scalar, as it appears linearly in the numerator and denominator of the formulas. $$ \begin{aligned} ( -r^{-1/2}, r^{-1/2} +r^{1/2}, -r^{1/2} ) &= ( e^{i\frac{\pi}{N}}, e^{i\frac{\pi}{N}} + e^{-i\frac{\pi}{N}}, e^{-i\frac{\pi}{N}} )\\ &= ( e^{i\frac{\pi}{N}}, 2 \cos \left( \frac{\pi}{N} \right), e^{-i\frac{\pi}{N}} ) \end{aligned} \tag {2} $$ The filter guys might recognize the same rescaled (acting as a shift) vector as: $$ z ( 1, -2 z^{-1} \cos \left( \omega \right), z^{-2} ) \tag {3} $$ When dotted with $(1,1,1)$, aka "DC" this vector becomes: $$ \begin{aligned} ( 1, -2 z^{-1} \cos \left( \omega \right), z^{-2} ) \cdot(1,1,1) &= 1 -2 z^{-1} \cos \left( \omega \right) + z^{-2} \\ &= (1)^2 + (z^{-1})^2 - 2 (1)(z^{-1}) \cos \left( \omega \right) \end{aligned} \tag {4} $$ The last equation is the Law of Cosines, so you know it isn't a contrived fluke.

The corresponding window function is: $$ w[n] = \sin \left( \frac{n}{N}\pi \right) \sin \left( \frac{n+1}{N}\pi \right) \tag {5} $$ What is notable is that it zeros out the last sample as well as the first. This can easily be confirmed by plugging in $n=0$ and $n=N-1$ into the equation. One factor covers one end, the other the other.

The question was posted in the forum on this site on whether anybody recognized this window function, or thought it was anything special. Only one expert stepped forward and confirmed it was unknown to them. This was not unexpected and similar to my experience with presenting other new ideas. Since no one recognized the vector that the rest of this article is based on, it is likely it is novel too.

The Original Formulation of the Family

Expanding on this observation is straightforward. A family of window functions can be built up by including one more sine term for each level. Originally, they were stacked so that the points on the ends were zeroed towards the middle. $$ \begin{matrix} 0 & 1 & 1 \\ 1 & \sin\left( \frac{n}{N}\pi \right) & \\ 2 & \sin\left( \frac{n}{N}\pi \right) \sin\left( \frac{n+1}{N}\pi \right) & \\ 3 & \sin\left( \frac{n-1}{N}\pi \right) \sin\left( \frac{n}{N}\pi \right) \sin\left( \frac{n+1}{N}\pi \right) & \\ 4 & \sin\left( \frac{n-1}{N}\pi \right) \sin\left( \frac{n}{N}\pi \right) \sin\left( \frac{n+1}{N}\pi \right) \sin\left( \frac{n+2}{N}\pi \right) & \\ \end{matrix} \tag {6} $$ This leads to the zeroing pattern shown on an eight sample frame:

   n =      01234567
        0 T|TTTTTTTT|T
        1 .|0...T...|0
   L =  2 0|0..tt..0|0
        3 0|00..T..0|0
        4 0|00.tt.00|0

The T's stand for the "Top" value. The symbol even looks made for the part. A dot is a non zeroed value. The vertical characters demarcate the frame. The even/odd pattern is obvious.

Left Fill Formulation

From a math point of view, filling zeroes from the left is equivalent and simpler to formulate. The distinction is one of referencing, not behavior. Here is the corresponding zeroing pattern:

    0 T|TTTTTTTT|T
    1 .|0...T...|0
    2 0|00..tt..|0
    3 0|000..T..|0
    4 0|0000.tt.|0

So, I worked all the math that way.

An Endian Transformation

After working through it for a while, rather than have the zeros left fill the frame, it makes more sense to have them fill from the right.

Sorry for any whiplash. Oh, you didn't feel it? I sure did. The symmetry is quite clear. Reverse the indexing direction and you get the equivalent definition so they have to be forward and backward symmetric.

The right zero padding family is: $$ \begin{aligned} W_0 &= 1 \\ W_1 &= \sin \left(( n + 1 ) \frac{\pi}{N} \right) \\ W_2 &= \sin \left(( n + 1 ) \frac{\pi}{N} \right) \sin \left(( n + 2 ) \frac{\pi}{N} \right) \\ W_3 &= \sin \left(( n + 1 ) \frac{\pi}{N} \right) \sin \left(( n + 2 ) \frac{\pi}{N} \right) \sin \left(( n + 3 ) \frac{\pi}{N} \right) \\ W_4 &= \sin \left(( n + 1 ) \frac{\pi}{N} \right) \sin \left(( n + 2 ) \frac{\pi}{N} \right) \sin \left(( n + 3 ) \frac{\pi}{N} \right) \sin \left(( n + 4 ) \frac{\pi}{N} \right) \\ \end{aligned} \tag {7} $$ It's easy to see that the first member zeroes out the $N-1$ sample. The next does that and $N-2$, and so on. The subscript to the window function indicates how many samples are zeroed out.

Here is the corresponding zeroing pattern for a frame size of nine:

    0 T|TTTTTTTTT|T
    1 .|...tt...0|0
    2 0|...T...00|0
    3 0|..tt..000|0
    4 0|..T..0000|0

For purposes of analysis, the future can be zeroed out for a little while so you don't have to wait for it to happen. Also, the zeroing allows the calculation of the DFT to be reduced if coded properly. The non-zero stretch is the stance on the signal when this is used as a window function. The zero padding is how zero padding should be done.

In other words, the placement of the zero stretch and non-zero stretch is simply a matter of referencing. The true behavioral reference is the peak of the curve.

The Simplified Formulation

The window functions can also be more simply represented by using a variable substitution for the discrete angles. $$ \begin{aligned} \psi &=\frac{n}{N}\pi \\ \chi &=\frac{1}{N}\pi = \frac{1}{2} \beta_1 = \frac{1}{2} \left( \frac{2\pi}{N} \right) \\ \end{aligned} \tag {8} $$ The $\beta_1$ is my consistent representation of 1/Nth of a circle. Note that $\chi$ is half of that. The sine function only goes half a cycle in the frame since $\psi=n\chi$ only takes half the root angle (a semi-root) step each sample. This means it can only zero out one sample within the DFT frame no matter how it is shifted.

Using the variable substitutions also loosens the tie to their presumed values and let's the equations be viewed on a continuous basis. Even though we are dealing with a specific case, we can think of it in a general framework. $$ \begin{aligned} W_0 &= 1 \\ W_1 &= \sin(\psi + \chi ) \\ W_2 &= \sin(\psi + \chi ) \sin(\psi + 2 \chi ) \\ W_3 &= \sin(\psi + \chi ) \sin(\psi + 2 \chi ) \sin(\psi + 3 \chi ) \\ W_4 &= \sin(\psi + \chi ) \sin(\psi + 2 \chi ) \sin(\psi + 3 \chi ) \sin(\psi + 4 \chi ) \\ W_5 &= \sin(\psi + \chi ) \sin(\psi + 2 \chi ) \sin(\psi + 3 \chi ) \sin(\psi + 4 \chi ) \sin(\psi + 5 \chi )\\ \end{aligned} \tag {9} $$ The window functions are a product of shifted Sines. They are very factorial like in their definition. $$ W_L = \prod_{l=1}^{L} \sin(\psi + l \cdot \chi ) = \prod_{l=1}^{L} \sin \left( \frac{n+l}{N}\pi \right) \tag {10} $$

The Recursive Formulation

The window family members can be defined via their predecessors, and values evaluated this way in code. $$ \begin{aligned} W_0 &= 1 \\ W_1 &= W_0 \sin(\psi + \chi ) \\ W_2 &= W_1 \sin(\psi + 2 \chi ) \\ W_3 &= W_2 \sin(\psi + 3 \chi ) \\ W_4 &= W_3 \sin(\psi + 4 \chi ) \\ W_5 &= W_4 \sin(\psi + 5 \chi )\\ \end{aligned} \tag {11} $$ A simple recursive definition is: $$ \begin{aligned} W_L &= W_{L-1} \sin(\psi + L \chi ) \\ \end{aligned} \tag {12} $$ Plainly, each next member has one more root. When aligned with samples they will be zeroed out. Ultimately a sample aligned $W_N$ will zero every sample in a $N$ sized frame, yet will not be the zero function. By symmetry each sample interval will be identical.

The definition of $W_0 = 1$ is one of convenience. Notice that is acts like a coefficient for the rest of the calculation. The same superstructure can be built on top of any $W_0$, without having to be recalculated.

The recursive definiton can be evaluated in either row major or column major order. Here is a code snippet from the program that produces the tables below:

#---- Set parameters

        N = 9
        L = 7

        theChi = np.pi / N

#---- Allocate the Family

        theFamily = []
        
        for l in range( L ):
          theFamily.append( np.zeros( N ) )
        
#---- Build the Zeroing Sine Family

        for n in range( N ):
          
          theFamily[0][n] = 1.0

          for l in range( 1, L ):
            theFamily[l][n] = theFamily[l-1][n] * np.sin( (n+l)*theChi )
        

There is a slightly better code snippet at the end of Appendix II and an even better one in Appendix V.

DFT Indexing and Framing

These DFTs are portrayed with the conventional $0$ to $N-1$ indexing. From a theoretical viewpoint, it is much simpler to consider only odd sized DFTs and to center the zero sample in the signal and the DC bin in the spectrum. However, it is well known that FFT implementations are most efficient having frames with power of two sizes and most are zero based. Just as the location of the zeroes can be slid around without behavioral consequence, so too can the choice of reference frames for the DFT be made.

The Fourier Formulation

There are binomials in the definitions, and they are multiplied together in patterns. This means the Pascal's triangle pattern is going to come into play. This is illustrated in Appendix III to generate the Fourier Series coefficients for the window function family.

As a result, the window functions can be defined by the sum of sine and cosines of the half fundamental for the frame and its harmonics.

The number of terms rises quickly for each family member. An algortihmic solution is fairly straight forward and was used to generate the demonstration grid. The member of the family can then be defined as a set of three member integer tuples "(coeffient, n step, 1 step)" and expanded using a double-wide semi-roots trig lookup table.

This allows for alternative formulas without powers, but their complexity makes this impractical. They are essential for the mathiness of it all.

Values in a Small Frame

Here are some values on an $N=9$ frame. Spinning a signal up by Nyquist before the DFT has the effect of shifting the bin values so the original DC ends up at Nyquist. For these displays, centering the DC is desirable.

  L =   0        1        2        3        4        5        6     

Window Function

  0  1.0000   0.3420   0.2198   0.1904   0.1875   0.1847   0.1599
  1  1.0000   0.6428   0.5567   0.5482   0.5399   0.4676   0.3005
  2  1.0000   0.8660   0.8529   0.8399   0.7274   0.4676   0.1599
  3  1.0000   0.9848   0.9698   0.8399   0.5399   0.1847   0.0000
  4  1.0000   0.9848   0.8529   0.5482   0.1875   0.0000  -0.0000
  5  1.0000   0.8660   0.5567   0.1904   0.0000  -0.0000   0.0000
  6  1.0000   0.6428   0.2198   0.0000  -0.0000   0.0000  -0.0000
  7  1.0000   0.3420   0.0000  -0.0000   0.0000  -0.0000   0.0000
  8  1.0000   0.0000  -0.0000   0.0000  -0.0000   0.0000  -0.0000

DFT of Window spun up by Nyquist

  0  1.0000   0.0000   0.0622   0.0000   0.0226   0.0000   0.0193
  1  1.0642   0.0000   0.0764   0.0000   0.0346   0.0000   0.0555
  2  1.3054   0.0000   0.1527   0.0000   0.1875   0.2813   0.2450
  3  2.0000   0.0000   0.8264   1.1250   1.0798   0.8098   0.4605
  4  5.7588   4.5000   3.6454   2.8486   2.0293   1.2407   0.6011
  5  5.7588   4.5000   3.6454   2.8486   2.0293   1.2407   0.6011
  6  2.0000   0.0000   0.8264   1.1250   1.0798   0.8098   0.4605
  7  1.3054   0.0000   0.1527   0.0000   0.1875   0.2813   0.2450
  8  1.0642   0.0000   0.0764   0.0000   0.0346   0.0000   0.0555

DFT of Window spun up by Nyquist and a half

  0  0.0000   0.1820   0.0000   0.0352   0.0000   0.0223   0.0000
  1  0.0000   0.1820   0.0000   0.0352   0.0000   0.0223   0.0000
  2  0.0000   0.2376   0.0000   0.0661   0.0000   0.0983   0.1406
  3  0.0000   0.4465   0.0000   0.3808   0.5625   0.5317   0.3561
  4  0.0000   1.9696   2.2500   2.0606   1.6197   1.0634   0.5455
  5  9.0000   5.6713   4.2286   3.1570   2.1822   1.3044   0.6204
  6  0.0000   1.9696   2.2500   2.0606   1.6197   1.0634   0.5455
  7  0.0000   0.4465   0.0000   0.3808   0.5625   0.5317   0.3561
  8  0.0000   0.2376   0.0000   0.0661   0.0000   0.0983   0.1406

The first thing to notice is that the window functions do indeed zero out the first some many samples according to the level.

The second two blocks show the "leakage" remediation capability. The first column is the no window, or frame rectangular window, window function, the second column is a half sine. These are known window functions. The third column is the work horse, a VonHann like window. The rest are "new". Notice that the DFTs in the last column have almost the same profile, making the appearance in the DFT very bin independent.

The even/odd pattern typical in DFT comes into play as well. Since the odd members of the family are oriented on the half bin, the DFT of the half twist is very concentrated in the spectrum. Likewise, the even members are the most concentrated on the whole bin and most leakage on the half twist. This distinction goes away as the levels climb.

Values in a Large Frame

Here are the first hundred members of the family on a frame of 630 samples in black. The red are the rescaled DFT values for the last ten members by steps of ten.



There's a lot to be seen in this graphic.

Most prominently, the window functions are approaching a Gaussian shape, and at some point will overshoot that. They are not true Gaussians. Likewise, the DFT values are also approaching a Gaussian shape.

When N is large and L is small, the window functions should behave very much like their Raised Sine counter parts. When L gets large compared to N, things get more interesting.

The Shrinking Window

For every level up in the family, the next member zeroes out one more sample. This shrinks the size of the samples used, but not the size of the DFT frame. It is as if there is a shorter sampling frame ($N-L$) followed by zero padding ($L$).

The Stance on the DFT

The zeroth member, the unit rectangle window that fits the frame, has a bin stance of one bin. Every additional member of the Zeroing Sine windows takes up one more bin width in the stance. For even N, the bin stance is on the half bins, and for odd N it is on the whole bins. The size of the bin stance is then $1+L$, leaving $N-(L+1)=(N-1) - L$ zero valued bins.

For odd sized bin stances, the spectrum is centered on DC. For even sized bin stances it shifts half a bin. This explains the stances being revealed in the even/odd pattern shown for the N=9 case above. The stances can be seen by summing across the horizontal columns in Appendix I. They follow the Pascal's triangle binomial distribution pattern, but not quite the value pattern.

The Very Special Family Member

So, as the number $L$ increases, in the signal domain there is a shrinking window of $N-L$ non-zeroed samples. Meanwhile in the spectrum, aka frequency domain, there is a growing bin stance of $L+1$ bins. They both look like Gaussians.

Could it be that if we line them up and that they might be multiples of each other? Finding the $L$ value for which the zero profile in the signal domain matches the spectrum is easy: $$ \begin{aligned} N - L &= L + 1 \\ L &= ( N - 1 ) / 2 \end{aligned} \tag {13} $$ $L$ will only be an integer with odd N. So, the peaks will only align on the non-zeroed/zeroed profiles for odd DFT frame sizes. Numerically, this is confirmed.

The $L=(N-1)/2$ member of odd $N$ families turns out (numerically, working on a proof) to be an exact base Discrete Hermite-Gaussian DFT Eigenvector. This was hoped for, and greatly satisfying when confirmed.

The Crazy Uncle Family Member

The even $N$ case presented quite a challenge. The technique that works was tried early and failed, so failure of the test, not the concept. So a lot of trails in the new territory were explored.

The fix is simple. Find the family member that takes the first half of the frame. Then add it to itself one spot over. This shifts the center half a bin and makes the number of non-zero bins match the DFT stance. The proof of why it works isn't that hard using the definition.

Likewise, if one window function can subtracted from a shifted version of itself (the difference operator), or any kind of combination, particularly binomial combinations, will yield similar curves. The rules still need to be worked out. For instance, a "tt" top slid and subtracted will yield a zero crossing, a "T" top won't.

It would be reasonable to expect to find the higher order Discrete Hermite-Gaussian eigenvectors among this extended set in a regular pattern. The reader is encouraged to find the pattern first by starting with the source code listing in Appendix V and making appropriate modifications, as I will be doing at some point. The mathematician reader is also encouraged to work out the same using the definition (10), as I will be doing at some point. [If you accomplish either before I do, please make reference in the comments.]

There will be another article (or two) on the Eigenvectors found. This article shows the path to the doorway of a whole set of new patterns.

Ideal for a Spectrogram

For a 1024 sample DFT, a window size of about 140 samples will cover a swath within the range of CD quality. That means a 140 sample range can be nestled up to the leading edge of real time data, with a latency of 70 samples, yet have 1024 sample resolution behind it. Sort of like having a 7X magnifying glass in terms of frequency resolution. This window is like the ideal corrective lens for the DFT so that continuous changes in the underlying parameters are undistorted in the spectrum.

Never is there any uncertainty involved in the smearing. The same pure tone will be fond in the place every time, at the center of the distribution. If you have a wavering/noisy tone, the best fit will be at the center and you smear will be wider. Since the first is known definitionally, the difference in smear widths can be used to measure the off-pure-tone-ness (distortion?).

For a spectrogram, on a log scale, standalone modes will be approximate parabolas (exact at center). This lead to simple and accurate interpolation for display purposes freeing the need to be bin aware for selection criteria.

Multiple Tone Decomposition

Every pure tone, no matter what the bin alignment, gets smeared into the same eigenvector Gaussian shape in the magnitude profile of the spectrum. It is the ideal manifestation of the DFT "acting like a FT", only smeared. The smearing should not be interpreted as "uncertainty", it is simply the mechanism to put all frequencies, no matter what their frequency fraction value is, on a non-discriminatory continuous scale. The width of the smear is well defined for a tone, so any distortion and noise will show up as a widening of that smear and can thus be measured.

The peak of that Gaussian is at the frequency on the spectrum's bin scale. Taking the log makes it a parabola (effectively) and finding the peak is trivial. See program output in the Gaussian Fit columns in Appendix II.  All the bins in the hood of the peak agree with where the peak is since they are assuming a Gaussian shape. Further away, that assumption weakens because a discrete Gaussian is not the same as a sampled Gaussian, a discrete sinc is not the same as a sampled sinc, a DFT is not the same as a FT, etc.

Once the frequency is known, a basis vector of bin values can be generated for that frequency by spinning it up to the calculated frequency which can be done on short segments for calculation savings. This is the equivalent of having bin value formulas for the bins. One dot product later, the amplitude and phase of the tone are known.

Decomposition can then proceed by picking the largest, measuring, removing it, until all the tones are done. Rinse and repeat. Same as my other approach, but using this windowed DFT instead of the raw one. This one may achieve as good as or equal to my other approach with fewer iterations.

The further the tones are spaced, the fewer passes needed.

Because it is an Eigenvector, the zero padding also exists in the spectrum. This means that for real valued tones between $\frac{\pi}{4}$ and $\frac{3\pi}{4}$ each component tone is completely protected against interference from its conjugate partner.

To the Window and Math Thereof Aficionados

You know who you are. Here's a toy to run tests on. Easy to implement, easy to relate, and clearly discreteness cognizant vs the Raised Sine which are the continuous limit of this family and are quite indiscrete. As N gets larger, the importance of recognizing discreteness diminishes.

A whole new class of windows having a special member of the family being the minimum width Discrete Hermite-Gaussian for its $N$.

A Gaussianish Eigenvector is as close as you are going to get to sampling a Gaussian moment in time and have each pure tone be a Gaussian in the DFT spectrum. That's kind of special, no?

This is the eagle eye lens of the DFT world. That's just a start.

How far can you zero pad inward before there is no longer a discrete Gaussian eigenvector possible? The answer is about halfway, even/odd conditions applying. This is the narrowest you can get exactly. If you are willing to accept an approximation, the effective signal frame can be narrowed further yet. For a given N, (Forget Hz, the DFT doesn't care about your sampling rate), this is the narrowest possible Heisenberg type pulse that will pass through the DFT unscathed.

What the eigenvectors are and how they work is largely known. What is new here is a much faster, complete, and accurate way to compute the members and more importantly a mathematical definition that lends itself to proofs well.

The Hermite-Gaussian functions are clearly the limit of these eigenvectors as N approaches infinity. The fit to a Gaussian at the peak for large N is extremely close.

Conclusion

This article was meant as an introduction and an invitation to explore a previously unrecognized family of DFT window functions. Then, the set of discrete Gaussian DFT eigenvectors popped up, seemingly out of nowhere, and changed the emphasis some. They were supposed to be a topic for a different article and a convergent search. This is better. Expect more on that.

There is no doubt that this is foundational material.

The heavier math will come in subsequent articles. The really heavy math will done by those for whom this material is more meaningful, and more in their wheelhouse, than yours truly

Afterword

In researching this topic, these are the papers that I have found that are most similar.  Their methodologies are different but Kudos to Kuznetsov for having solved the problem I have framed.  I am now working on making conceptual connections between our differing approaches.


"Explicit Hermite-type eigenvectors of the discrete Fourier transform", Alexey Kuznetsov,
https://arxiv.org/abs/1501.07646

"Minimal Hermite-type eigenbasis of the discrete Fourier transform", Alexey Kuznetsov, Mateusz Kwasnicki,
http://arxiv.org/abs/1706.08740v1

"Analytic Expressions of Two Discrete Hermite–Gauss Signals", F. N. Kong

IEEE TRANSACTIONS ON CIRCUITS AND SYSTEMS—II: EXPRESS BRIEFS, VOL. 55, NO. 1, JANUARY 2008.

Appendix I. A Set of Smallish Frames

=====================================================================================
N =   8 Non-zeros = 4   Eigen Member (Zeroes) = 4 
       Bin Stance = 5   Spun up by 3 Peak at 1.5 

---- ----------  --------------------  ------------   ------------------    ---------
RofU Window      Log(Window) Parabola  Gaussian Fit   Spectrum SemiRoots    Eigenish
n,k  W_L[n]      A[n]   B[n]   Peak    StdDev  Mean   Mag[k]    Phase[k]    Measure 
---- ----------  --------------------  ------------   ------------------    ---------
  0:  2.500e-01   1.134  -0.252  0.11   nan   0.11  | 9.061e-01     4.50 .  0.7803613
  1:\ 6.036e-01  -0.441   0.441  1.50  1.51   0.50  o 1.600e+00     1.50 t  1.0671769
  2:/ 6.036e-01  -0.441  -0.441  1.50  1.51  -0.50  o 1.600e+00    -1.50 t  1.0671769
  3:  2.500e-01    -inf    -inf   nan  0.00    nan  | 9.061e-01    -4.50 .  0.7803613
  4:!-0.000e+00     nan    -inf   nan   nan    nan  : 1.802e-01    -7.50 0 -0.0000000
  5:! 0.000e+00     nan     nan   nan   nan    nan  : 4.229e-02    -2.50 0  0.0000000
  6:!-0.000e+00     nan     nan   nan   nan    nan  : 4.229e-02     2.50 0 -0.0000000
  7:! 0.000e+00     nan     inf   nan   nan    nan  : 1.802e-01     7.50 0  0.0000000

=====================================================================================
N =   9 Non-zeros = 5   Eigen Member (Zeroes) = 4 
       Bin Stance = 5   Spun up by 4 Peak at 2.0 

---- ----------  --------------------  ------------   ------------------    ---------
RofU Window      Log(Window) Parabola  Gaussian Fit   Spectrum SemiRoots    Eigenish
n,k  W_L[n]      A[n]   B[n]   Peak    StdDev  Mean   Mag[k]    Phase[k]    Measure 
---- ----------  --------------------  ------------   ------------------    ---------
  0:  1.875e-01   1.366  -0.308  0.11   nan   0.11  | 5.625e-01     8.00 .  1.0000000
  1:  5.399e-01  -0.380   0.678  1.89  1.62   0.89  | 1.620e+00     4.00 .  1.0000000
  2:> 7.274e-01  -0.298   0.000  2.00  1.83   0.00  O 2.182e+00    -0.00 T  1.0000000
  3:  5.399e-01  -0.380  -0.678  2.11  1.62  -0.89  | 1.620e+00    -4.00 .  1.0000000
  4:  1.875e-01    -inf    -inf   nan  0.00    nan  | 5.625e-01    -8.00 .  1.0000000
  5:!-0.000e+00     nan    -inf   nan   nan    nan  : 1.001e-15     2.64 0 -0.0000000
  6:! 0.000e+00     nan     nan   nan   nan    nan  : 5.661e-16     3.93 0  0.0000000
  7:!-0.000e+00     nan     nan   nan   nan    nan  : 4.663e-16    -6.33 0 -0.0000000
  8:! 0.000e+00     nan     inf   nan   nan    nan  : 8.846e-16     5.78 0  0.0000000

=====================================================================================
N =  10 Non-zeros = 5   Eigen Member (Zeroes) = 5 
       Bin Stance = 6   Spun up by 4 Peak at 2.0 

---- ----------  --------------------  ------------   ------------------    ---------
RofU Window      Log(Window) Parabola  Gaussian Fit   Spectrum SemiRoots    Eigenish
n,k  W_L[n]      A[n]   B[n]   Peak    StdDev  Mean   Mag[k]    Phase[k]    Measure 
---- ----------  --------------------  ------------   ------------------    ---------
  0:  1.398e-01   1.546  -0.422  0.14   nan   0.14  | 6.317e-01     8.00 .  0.6995962
  1:  4.301e-01  -0.402   0.722  1.90  1.58   0.90  | 1.374e+00     4.00 .  0.9896878
  2:> 5.920e-01  -0.319   0.000  2.00  1.77   0.00  O 1.732e+00    -0.00 T  1.0810389
  3:  4.301e-01  -0.402  -0.722  2.10  1.58  -0.90  | 1.374e+00    -4.00 .  0.9896878
  4:  1.398e-01    -inf    -inf   nan  0.00    nan  | 6.317e-01    -8.00 .  0.6995962
  5:!-0.000e+00     nan    -inf   nan   nan    nan  : 1.001e-01     8.00 0 -0.0000000
  6:! 0.000e+00     nan     nan   nan   nan    nan  : 1.757e-02    -6.00 0  0.0000000
  7:!-0.000e+00     nan     nan   nan   nan    nan  : 1.128e-02    -0.00 0 -0.0000000
  8:! 0.000e+00     nan     nan   nan   nan    nan  : 1.757e-02     6.00 0  0.0000000
  9:!-0.000e+00     nan     inf   nan   nan    nan  : 1.001e-01    -8.00 0 -0.0000000

=====================================================================================
N =  11 Non-zeros = 6   Eigen Member (Zeroes) = 5 
       Bin Stance = 6   Spun up by 5 Peak at 2.5 

---- ----------  --------------------  ------------   ------------------    ---------
RofU Window      Log(Window) Parabola  Gaussian Fit   Spectrum SemiRoots    Eigenish
n,k  W_L[n]      A[n]   B[n]   Peak    StdDev  Mean   Mag[k]    Phase[k]    Measure 
---- ----------  --------------------  ------------   ------------------    ---------
  0:  1.036e-01   1.762  -0.505  0.14   nan   0.14  | 3.437e-01    -9.50 .  1.0000000
  1:  3.641e-01  -0.368   0.888  2.21  1.65   1.21  | 1.208e+00     7.50 .  1.0000000
  2:\ 6.127e-01  -0.260   0.260  2.50  1.96   0.50  o 2.032e+00     2.50 t  1.0000000
  3:/ 6.127e-01  -0.260  -0.260  2.50  1.96  -0.50  o 2.032e+00    -2.50 t  1.0000000
  4:  3.641e-01  -0.368  -0.888  2.79  1.65  -1.21  | 1.208e+00    -7.50 .  1.0000000
  5:  1.036e-01    -inf    -inf   nan  0.00    nan  | 3.438e-01     9.50 .  1.0000000
  6:!-0.000e+00     nan    -inf   nan   nan    nan  : 1.415e-15    -5.98 0 -0.0000000
  7:! 0.000e+00     nan     nan   nan   nan    nan  : 1.405e-15    10.44 0  0.0000000
  8:!-0.000e+00     nan     nan   nan   nan    nan  : 1.226e-15    -5.82 0 -0.0000000
  9:! 0.000e+00     nan     nan   nan   nan    nan  : 2.220e-16    11.00 0  0.0000000
 10:!-0.000e+00     nan     inf   nan   nan    nan  : 1.241e-16     3.88 0 -0.0000000

=====================================================================================

Appendix II. An Example Medium Frame EigenVector

This is the special family case for $N=3^4=81$ and $L=40$. Note that CD quality sound only requires bins 4 through 36 further reducing the DFT calculation burden. The last column shows numerically that it is indeed an eigenvector. Medium being a relative measure on an arbitrary scale of interpretive weighting. IMO.

=====================================================================================
N =  81 Non-zeros = 41   Eigen Member (Zeroes) = 40 
       Bin Stance = 41   Spun up by 40 Peak at 20.0 

---- ----------  --------------------  ------------   ------------------    ---------
RofU Window      Log(Window) Parabola  Gaussian Fit   Spectrum SemiRoots    Eigenish
n,k  W_L[n]      A[n]   B[n]   Peak    StdDev  Mean   Mag[k]    Phase[k]    Measure 
---- ----------  --------------------  ------------   ------------------    ---------
  0:  8.185e-12  14.389 -11.139  0.39   nan   0.39  | 7.367e-11   -10.00 .  1.0000000
  1:  2.111e-10  -0.347   2.903  5.18  1.70   4.18  | 1.900e-09   -50.00 .  1.0000000
  2:  2.719e-09  -0.204   2.352  7.78  2.22   5.78  | 2.447e-08    72.00 .  1.0000000
  3:  2.331e-08  -0.145   2.003  9.90  2.62   6.90  | 2.098e-07    32.00 .  1.0000000
  4:  1.495e-07  -0.113   1.745 11.69  2.97   7.69  | 1.345e-06    -8.00 .  1.0000000
  5:  7.638e-07  -0.094   1.538 13.22  3.27   8.22  | 6.875e-06   -48.00 .  1.0000000
  6:  3.237e-06  -0.080   1.364 14.52  3.53   8.52  | 2.913e-05    74.00 .  1.0000000
  7:  1.169e-05  -0.070   1.214 15.64  3.77   8.64  | 1.052e-04    34.00 .  1.0000000
  8:  3.668e-05  -0.063   1.080 16.58  3.99   8.58  | 3.301e-04    -6.00 .  1.0000000
  9:  1.015e-04  -0.057   0.960 17.37  4.18   8.37  | 9.132e-04   -46.00 .  1.0000000
 10:  2.503e-04  -0.053   0.850 18.03  4.35   8.03  | 2.252e-03    76.00 .  1.0000000
 11:  5.553e-04  -0.049   0.748 18.57  4.50   7.57  | 4.998e-03    36.00 .  1.0000000
 12:  1.116e-03  -0.047   0.652 19.00  4.63   7.00  | 1.005e-02    -4.00 .  1.0000000
 13:  2.044e-03  -0.044   0.561 19.33  4.75   6.33  | 1.840e-02   -44.00 .  1.0000000
 14:  3.427e-03  -0.042   0.474 19.58  4.85   5.58  | 3.084e-02    78.00 .  1.0000000
 15:  5.275e-03  -0.041   0.390 19.76  4.94   4.76  | 4.748e-02    38.00 .  1.0000000
 16:  7.481e-03  -0.040   0.309 19.88  5.00   3.88  | 6.733e-02    -2.00 .  1.0000000
 17:  9.796e-03  -0.039   0.230 19.95  5.06   2.95  | 8.816e-02   -42.00 .  1.0000000
 18:  1.186e-02  -0.039   0.153 19.99  5.10   1.99  | 1.068e-01    80.00 .  1.0000000
 19:  1.330e-02  -0.038   0.076 20.00  5.12   1.00  | 1.197e-01    40.00 .  1.0000000
 20:> 1.382e-02  -0.038   0.000 20.00  5.13   0.00  O 1.243e-01    -0.00 T  1.0000000
 21:  1.330e-02  -0.038  -0.076 20.00  5.12  -1.00  | 1.197e-01   -40.00 .  1.0000000
 22:  1.186e-02  -0.039  -0.153 20.01  5.10  -1.99  | 1.068e-01   -80.00 .  1.0000000
 23:  9.796e-03  -0.039  -0.230 20.05  5.06  -2.95  | 8.816e-02    42.00 .  1.0000000
 24:  7.481e-03  -0.040  -0.309 20.12  5.00  -3.88  | 6.733e-02     2.00 .  1.0000000
 25:  5.275e-03  -0.041  -0.390 20.24  4.94  -4.76  | 4.748e-02   -38.00 .  1.0000000
 26:  3.427e-03  -0.042  -0.474 20.42  4.85  -5.58  | 3.084e-02   -78.00 .  1.0000000
 27:  2.044e-03  -0.044  -0.561 20.67  4.75  -6.33  | 1.840e-02    44.00 .  1.0000000
 28:  1.116e-03  -0.047  -0.652 21.00  4.63  -7.00  | 1.005e-02     4.00 .  1.0000000
 29:  5.553e-04  -0.049  -0.748 21.43  4.50  -7.57  | 4.998e-03   -36.00 .  1.0000000
 30:  2.503e-04  -0.053  -0.850 21.97  4.35  -8.03  | 2.252e-03   -76.00 .  1.0000000
 31:  1.015e-04  -0.057  -0.960 22.63  4.18  -8.37  | 9.132e-04    46.00 .  1.0000000
 32:  3.668e-05  -0.063  -1.080 23.42  3.99  -8.58  | 3.301e-04     6.00 .  1.0000000
 33:  1.169e-05  -0.070  -1.214 24.36  3.77  -8.64  | 1.052e-04   -34.00 .  1.0000000
 34:  3.237e-06  -0.080  -1.364 25.48  3.53  -8.52  | 2.913e-05   -74.00 .  1.0000000
 35:  7.638e-07  -0.094  -1.538 26.78  3.27  -8.22  | 6.875e-06    48.00 .  1.0000000
 36:  1.495e-07  -0.113  -1.745 28.31  2.97  -7.69  | 1.345e-06     8.00 .  1.0000000
 37:  2.331e-08  -0.145  -2.003 30.10  2.62  -6.90  | 2.098e-07   -32.00 .  1.0000000
 38:  2.719e-09  -0.204  -2.352 32.22  2.22  -5.78  | 2.447e-08   -72.00 .  1.0000000
 39:  2.111e-10  -0.347  -2.903 34.82  1.70  -4.18  | 1.900e-09    50.00 .  1.0000000
 40:  8.185e-12    -inf    -inf   nan  0.00    nan  | 7.367e-11    10.00 .  1.0000001
 41:!-0.000e+00     nan    -inf   nan   nan    nan  : 2.085e-17   -75.09 0 -0.0000000
 42:! 0.000e+00     nan     nan   nan   nan    nan  : 3.766e-17    45.45 0  0.0000000
 43:!-0.000e+00     nan     nan   nan   nan    nan  : 3.331e-17    12.82 0 -0.0000000
 44:! 0.000e+00     nan     nan   nan   nan    nan  : 3.137e-17   -27.39 0  0.0000000
 45:!-0.000e+00     nan     nan   nan   nan    nan  : 3.775e-17   -57.64 0 -0.0000000
 46:! 0.000e+00     nan     nan   nan   nan    nan  : 4.542e-17    59.84 0  0.0000000
 47:!-0.000e+00     nan     nan   nan   nan    nan  : 5.298e-17    19.41 0 -0.0000000
 48:! 0.000e+00     nan     nan   nan   nan    nan  : 5.180e-17   -16.06 0  0.0000000
 49:!-0.000e+00     nan     nan   nan   nan    nan  : 4.405e-17   -63.38 0 -0.0000000
 50:! 0.000e+00     nan     nan   nan   nan    nan  : 4.065e-17    61.60 0  0.0000000

=====================================================================================

Here is a more efficient code snippet for calculating the family of window functions, ending at the closest to, or on, an eigenvector. The in between family values need not be saved as is shown in the code.

#---- Build the Semi-Roots table

        theSemiRoots = np.zeros( 2*N, dtype=complex )
        
        for sr in range( 2 * N ):
          theSemiRoots[sr] = np.exp( 1j * sr * argChi )

#---- Build the Zeroing Sine Family

        for n in range( N ):
          useFamily[0,n] = 1.0

          for l in range( 1, L + 1 ):
            sr = n+l   # 2 * ( n + l ) + 1
            useFamily[l,n] = useFamily[l-1,n] * theSemiRoots[sr].imag

Appendix III. Finding the Fourier Coefficients

The is the split open Pascal's triangle (aka Binomial Distribution) of the family of window functions. The sums across the rows add up to binomial coefficients. Each row corresponds to half a bin width in the spectrum stance calculation. The columns represent the spread due to walking the zeroes inward. Each column represents half a sample width in a sense, and always add up to zero. The rest is up to you to puzzle out for now.

  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0

  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 -1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0

  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 -1  0 -1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0

  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0 -1  0 -1  0 -1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  1  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 -1  0  0  0  0  0  0  0  0  0  0  0  0  0

  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0 -1  0 -1  0 -1  0 -1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  1  0  1  0  2  0  1  0  1  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 -1  0 -1  0 -1  0 -1  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0

  0  0  0  0  0  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0 -1  0 -1  0 -1  0 -1  0 -1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  1  0  1  0  2  0  2  0  2  0  1  0  1  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0 -1  0 -1  0 -2  0 -2  0 -2  0 -1  0 -1  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  1  0  1  0  1  0  1  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 -1  0  0  0  0  0  0

  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0 -1  0 -1  0 -1  0 -1  0 -1  0 -1  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  1  0  1  0  2  0  2  0  3  0  2  0  2  0  1  0  1  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0 -1  0 -1  0 -2  0 -3  0 -3  0 -3  0 -3  0 -2  0 -1  0 -1  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0  1  0  2  0  2  0  3  0  2  0  2  0  1  0  1  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0 -1  0 -1  0 -1  0 -1  0 -1  0 -1  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  1  0

Appendix IV. The Starter List of EigenVectors

Here are the starting elements for the first few eigenvectors.

  N  L-ish  w[0]    w[0]    w[0]    w[0]    w[0]    w[0]    w[0]    Correlation
---  ----- ------  ------  ------  ------  ------  ------  ------   -----------
  4   1.5  0.7071  1.4142  0.7071  0.0000                            1.00000000
  5   2    0.5590  0.9045  0.5590 -0.0000  0.0000                    1.00000000
  6   2.5  0.4330  1.1830  1.1830  0.4330  0.0000  0.0000            1.00000000
  7   3    0.3307  0.7431  0.7431  0.3307 -0.0000  0.0000 -0.0000    1.00000000
  8   3.5  0.2500  0.8536  1.2071  0.8536  0.2500  0.0000  0.0000    1.00000000
  9   4    0.1875  0.5399  0.7274  0.5399  0.1875 -0.0000  0.0000    1.00000000
 10   4.5  0.1398  0.5699  1.0221  1.0221  0.5699  0.1398  0.0000    1.00000000
 11   5    0.1036  0.3641  0.6127  0.6127  0.3641  0.1036 -0.0000    1.00000000
 12   5.5  0.0765  0.3622  0.7805  0.9896  0.7805  0.3622  0.0765    1.00000000
 13   6    0.0563  0.2337  0.4702  0.5835  0.4702  0.2337  0.0563    1.00000000
 14   6.5  0.0413  0.2225  0.5572  0.8477  0.8477  0.5572  0.2225    1.00000000
 15   7    0.0303  0.1447  0.3384  0.4986  0.4986  0.3384  0.1447    1.00000000
 16   7.5  0.0221  0.1332  0.3793  0.6696  0.8028  0.6696  0.3793    1.00000000
 17   8    0.0161  0.0873  0.2324  0.3951  0.4681  0.3951  0.2324    1.00000000
 18   8.5  0.0117  0.0782  0.2491  0.4989  0.6932  0.6932  0.4989    1.00000000
 19   9    0.0085  0.0515  0.1539  0.2961  0.4036  0.4036  0.2961    1.00000000
 20   9.5  0.0062  0.0452  0.1590  0.3556  0.5597  0.6484  0.5597    1.00000000
 21  10    0.0045  0.0299  0.0990  0.2125  0.3267  0.3755  0.3267    1.00000000
 22  10.5  0.0032  0.0258  0.0992  0.2447  0.4294  0.5631  0.5631    1.00000000
 23  11    0.0023  0.0172  0.0623  0.1473  0.2516  0.3258  0.3258    1.00000000
 24  11.5  0.0017  0.0145  0.0608  0.1637  0.3163  0.4618  0.5226    1.00000000
 25  12    0.0012  0.0097  0.0384  0.0992  0.1863  0.2676  0.3012    1.00000000
 26  12.5  0.0009  0.0081  0.0367  0.1070  0.2253  0.3618  0.4557    1.00000000
 27  13    0.0006  0.0055  0.0233  0.0652  0.1335  0.2104  0.2625    1.00000000
 28  13.5  0.0005  0.0045  0.0218  0.0685  0.1562  0.2731  0.3781    1.00000000
 29  14    0.0003  0.0030  0.0139  0.0421  0.0930  0.1594  0.2181    1.00000000
 30  14.5  0.0002  0.0025  0.0128  0.0431  0.1057  0.1998  0.3011    1.00000000
 31  15    0.0002  0.0017  0.0082  0.0266  0.0633  0.1172  0.1741    1.00000000
 32  15.5  0.0001  0.0014  0.0075  0.0268  0.0701  0.1424  0.2316    1.00000000
 33  16    0.0001  0.0009  0.0048  0.0166  0.0423  0.0839  0.1344    1.00000000
 34  16.5  0.0001  0.0007  0.0043  0.0164  0.0457  0.0991  0.1731    1.00000000
 35  17    0.0000  0.0005  0.0028  0.0102  0.0277  0.0587  0.1008    1.00000000
 36  17.5  0.0000  0.0004  0.0025  0.0099  0.0293  0.0677  0.1261    1.00000000
 37  18    0.0000  0.0003  0.0016  0.0062  0.0179  0.0402  0.0737    1.00000000
 38  18.5  0.0000  0.0002  0.0014  0.0060  0.0186  0.0454  0.0898    1.00000000
 39  19    0.0000  0.0001  0.0009  0.0037  0.0114  0.0271  0.0527    1.00000000
 40  19.5  0.0000  0.0001  0.0008  0.0035  0.0116  0.0300  0.0627    1.00000000
 41  20    0.0000  0.0001  0.0005  0.0022  0.0071  0.0180  0.0370    1.00000000

Appendix V. The Source Code Listing for the EigenVectors

import numpy as np

#========================================================================
def main():

        for m in range( 1, 25 ):
          for f in range( 4 ):
            N = 4 * m + f
            RunCase( N )
        
#========================================================================
def RunCase( N ):

#---- Calculate semi-root size

        theChi = np.pi / N
  
#---- Build the semi-roots table

        theSemiRoots = np.zeros( 2*N, dtype=complex )
        
        for sr in range( N ):
          theSemiRoots[sr]   = np.exp( 1j * sr * theChi )
          theSemiRoots[N+sr] = -theSemiRoots[sr]
          
#---- Calculate the ZeroingSine family values

        theZeroingSines = np.zeros( ( N, N ) )
        
        theZeroingSines[0:] = 1.0
        
        for l in range( 1, N ):
          for n in range( N ):
            theZeroingSines[l,n] = theZeroingSines[l-1,n] * theSemiRoots[n+l].imag

#---- Deal with Odd or Even

        theDisplay = "%3d " % N

        if ( N & 1 ) == 1 :
           L = ( N - 1 ) >> 1 
           theDisplay += HandleOdd( N, L, theZeroingSines )
        else:   
           L = ( N >> 1 ) - 1
           theDisplay += HandleEven( N, L, theZeroingSines )
           
#---- Print case

        print( theDisplay )
        
#========================================================================
def HandleOdd( N, L, argZeroingSiness ):

#---- Print the Results

        theZeroingSine = argZeroingSiness[L,]

#---- Print line

        theDisplay    = DisplayLine(    N, L, theZeroingSine )
        theEvaluation = EvaluateSingle( N, L, theZeroingSine )

        return theDisplay + " " + theEvaluation
        
#========================================================================
def HandleEven( N, L, argZeroingSiness ):

#---- Build a mutt

        theBudd  = argZeroingSiness[L+1,] 
        
        theMutt  = theBudd
        theMutt += np.roll( theBudd, 1 )

#---- Print line

        theDisplay    = DisplayLine(    N, L + 0.5, theMutt )
        theEvaluation = EvaluateSingle( N, L,       theMutt )

        return theDisplay + " " + theEvaluation
 
#========================================================================
def DisplayLine( N, L, argZeroingSines ):

        if L - int( L ) == 0 :
           theDisplay = "%3d  " % L
        else:   
           theDisplay = "%5.1f" % L
           
        theTop = N
        if theTop > 7 : theTop = 7
           
        for n in range( theTop ):
          theDisplay += "%8.4f" % argZeroingSines[n]

        return ( theDisplay + 100 * " " )[:64]
                  
#========================================================================
def EvaluateSingle( N, L, argZeroingSines ):

#---- Set stepper

        theStepSize = ( N - L - 1 ) * 0.5
        theStepper  = np.exp( 1j * theStepSize * 2.0 * np.pi / N )
          
#---- Spin up

        theNorm = np.sqrt( N )

        theSpinner = ( 1 + 0j ) * theNorm
        theSpunUp  = np.zeros( N, dtype=complex )
        
        for n in range( N ):
          theSpunUp[n] = argZeroingSines[n] * theSpinner
          theSpinner  *= theStepper
          
#---- Take spectrum        
        
        theSpectrum = np.fft.fft( theSpunUp )
        theProfile  = np.abs( theSpectrum )

        theCosine = argZeroingSines.dot( theProfile ) \
         / np.sqrt( argZeroingSines.dot( argZeroingSines  ) \
                 * theProfile.dot( theProfile ) ) 

        return "%10.8f" % theCosine

#========================================================================
main()

Previous post by Cedron Dawg:
   A Two Bin Solution

[ - ]
Comment by neiroberAugust 20, 2020

Cedron,

Thanks for these interesting window functions.  I calculated some figures of merit for your windows -- see the table.  The W2 window has essentially identical performance as the Hann window.  

As the number of factors in the window increases, the noise bandwidth/process loss increases, while the scallop loss and first sidelobe level decrease.  (Also, the main lobe bandwidth increases as the number of factors increases).

I calculated noise bw, proc loss, and scallop loss using the Matlab code listed in this post.

regards,

Neil

cedron windows fom_85640.png

[ - ]
Comment by CedronAugust 20, 2020
Hi Neil,

Thank you so much, these are what I was asking for.  I'm glad they turned out as expected.

I would be curious if you might add an L=(N-1)/2 case for an N=4m+1 odd case.  Maybe compare it to a Raised Sine of the same power, and draw one of those sidelobe pictures.  It should be very similar to a Gaussian window on the first half of the frame and zeros on the second.  It is only for very small N, say N < 10, that I expect any significant difference between the two families (Zeroing Sines and Raised Sines) to occur.  If it turns out interesting and you write an article about it, that would be awesome.  

Yes, the center lobe gets fatter until it matches the window function.  That's what makes it an eigenvector (in the cases that are).

It isn't really the performance characteristics that make these so special.  Instead, it is their role as a theoretical foundation for finding the eigenvectors.  The more I am researching those the more I am realizing that this is the "missing piece".

Ced

To post reply to a comment, click on the 'reply' button attached to each comment. To post a new comment (not a reply to a comment) check out the 'Write a Comment' tab at the top of the comments.

Registering will allow you to participate to the forums on ALL the related sites and give you access to all pdf downloads.

Sign up

I agree with the terms of use and privacy policy.

Try our occasional but popular newsletter. VERY easy to unsubscribe.
or Sign in