# tapers.jl

This unit implements eight tapering windows and the discrete prolate spheroidal sequences, the latter via the DSP package.

## TaperKind

```
@enum TaperKind begin
rectangular = 1
triangular = 2
hann = 3
hamming = 4
blackman = 5
harris4 = 6
riesz = 7
parzen = 8
slepian = 9
end
```

Those two identifiers conflicts with the DSP package. Until a better solution is found, invoke them as `FourierAnalysis.hamming`

and `FourierAnalysis.blackman`

.

The Hann tapering window is also known as 'squared cosine' window and a the Riesz window is similar to a window known as the 'cosine' window.

The design of tapering windows implies a trade-off between the *equivalent noise bandwidth* (enb), the energy of the *first sidelobe* (fsl) and the rate of *sidelobe falloff* (slf). The characteristics of the implemented tapering windows are reported in the following table:

window | notable points | enb(bins) | fsl(dB) | slf(dB/octave) |
---|---|---|---|---|

rectangular | 1 everywhere | 1 | -13 | - 6 |

triangular | 0 at boundaries | 1.33 | -26 | -12 |

hann | 0 at boundaries | 1.50 | -32 | -18 |

hamming | >0 at boundaries | 1.36 | -43 | - 6 |

blackman | 0 at boundaries | 1.73 | -58 | -18 |

harris4 | >0 at boundaries | 2 | -92 | - 6 |

riesz | 0 at boundaries | 1.2 | -21 | -12 |

parzen | >0 at boundaries | 1.92 | -53 | -24 |

The harris4 tapering window features excellent first sidelobe (-92dB) and sidelob falloff (-6dB rate), at the expenses of the highest equivalent noise bandwidth among all. Since this latter parameter is not critical in many applications, this window is employed as default by all *FourierAnalysis* constructors of objects in the frequency domain.

For reducing the variance of the spectral estimations, use the (Slepian) *discrete prolate spheroidal sequences (dpss)* multi-tapering (see `slepians`

).

## Taper

Tapering windows in **FourirAnalysis** are encapsulated in the following structure:

```
struct Taper
y :: Union{Vector{T}, Matrix{T}} where T<:Real
kind :: TaperKind
α :: Real
n :: Int
end
```

The fields of the structure are:

`y`

, a real vector holding the tapering window, but for Slepian multi-tapers, for which this is a matrix holding in its columns the dpss`kind`

, the tapering window(s) as a TaperKind`α`

, a parameter for the tapering window(s). This is needed only for dpss`n`

, the number of tapering windows. It is >1 only for dpss.

If you need to construct *Taper* objects for single tapering windows, use the universal `taper`

constructor. For constructing *dpss* use the specialized constructor `slepians`

.

`FourierAnalysis.taper`

— Function```
function taper( kind :: TaperKind,
wl :: Int;
α :: Real = 2.,
n :: Int = ceil(Int, 2*α)-1,
padding :: Int = 0,
type :: Type{T} = Float64) where T<:Union{Real, Complex}
```

Universal constructor of Taper objects, given a tapering window `kind`

, of type TaperKind and the window length `wl`

.

Return a vector of length `wl`

for all types of tapers, but for the dpss (Slepian multi-tapers), for which return a matrix of size `wl`

x `n`

.

If optional keyword argument `padding`

is >0, then the actual window length will be `wl`

+ `padding`

.

The `type`

optional keyword argument can be use to specify the the type of elements of the typering window. By default, this is the `Float64`

type.

Optional keywords arguments `α`

and `n`

currently apply only for slepian multi-tapering (*discrete prolate spheroidal sequences*):

`α`

is the *half bandwidth* (hbw) parameter as per the DSP.jl package. This unit is used in many dpss implementations and it is often reported that "typical values" for `α`

are 2, 2.5, 3, 3.5 or 4. However, the optimal smoothing increases with the ratio between window length and sampling rate, thus these values in absolute terms are not useful. In fact, the larger the *hbw* and the higher `n`

, the smoother the spectra will be (variance reduction). In order to overcome these difficulties, for Slepian's multitapering *FourirAnalysis* implements the `slepians`

constructor, which allows the bandwidth parameter to be given in Hz and the number of tapering windows to be chosen automatically.

`n`

is the number of tapering windows. For slepian tapers this is the number of the discrete prolate spheroidal sequences. As in the DSP package, by default it is set to `ceil(Int, 2*α)-1`

, however, depending on how large this number is, low eigenvalues may correspond to the last sequences, therefore those should be discarded.

**See**: plot tapering windows.

**Examples**:

```
using FourierAnalysis
## Use the constructor
sr, t, f, a = 128, 128, 10, 0.5
# create a sinusoidal superimposed to white noise
v=sinusoidal(a, f, sr, t*16, 0) + randn(t*16)
# create a data matrix
X=broadcast(+, v, randn(t*16, 3))*randn(3, 3)
# compute spectra using hamming tapering window
# we need to prepend 'FourierAnalysis.' since `hamming`
# is declared also in DSP.jl
H=taper(FourierAnalysis.hamming, t)
S=spectra(X, sr, t; tapering=H)
# you can obtain the same thing with
S=spectra(X, sr, t; tapering=H)
# which will create the hamming tapering window on the fly,
# thus calling explicitly the constructor is interesting
# only if you need to reuse the same tapering window many times.
## Plot tapering windows using the standard plot function
using Plots
tapers=[TaperKind(i) for i=1:8]
X=zeros(t, 8)
for i=1:8 X[:, i] = taper(tapers[i], t).y end
mylabels=Array{String}(undef, 1, 8)
for i=1:8 mylabels[1, i]=string(tapers[i]) end
plot(X; labels=mylabels)
## using the recipe declared in recipes.jl
plot(taper(parzen, 256))
plot(taper(slepian, 256, α=4, n=7))
```

`FourierAnalysis.slepians`

— FunctionConstruct a Taper objects holding Slepian's multi-tapering *discrete prolate spheroidal sequences*, given sampling rate `sr`

, window length `wl`

and the `bandwidth`

argument in Hz. For EEG data, 1<=bandwidth<=2 is an adequate choice.

The 'half-bandwidth' parameter `α`

used in the DSP package and in the universal Taper constructor is set as

` `α=(bandwidth/2)*wl/sr`.`

The optimal number of dpss is heuristically set to

` `n=max(1, trunc(Int, 2*α)-trunc(Int, log(2*α)))`.`

The created object can be passed as argument in constructors `spectra`

, `crossSpectra`

and `coherence`

.

**See**: plot tapering windows.

**Examples**:

```
using FourierAnalysis
sr, t, f, a = 128, 128, 10, 0.5
# create a sinusoidal superimposed to white noise
v=sinusoidal(a, f, sr, t*16, 0) + randn(t*16)
# create a data matrix
X=broadcast(+, v, randn(t*16, 3))*randn(3, 3)
# compute spectra using slepian multi-tapering with bandwidth 1.5
H=slepians(sr, t, 2)
S=spectra(X, sr, t; tapering=H)
using Plots
plot(H)
plot(S)
```

`FourierAnalysis.taperinfo`

— Function`function taperinfo(taper::Taper)`

Return the name of the tapering window(s) encapsulated in the Taper object as a string.

Only for Slepian's discrete prolate spheroidal sequences (dpss), their parameters, namely, $α$ (half-bandwidth) and $n$ (number of windows), are reported within parentheses as well.

**Examples**:

```
H=taper(hamming, 128*8)
taperinfo(H)
H=slepians(128, 128*8, 2)
taperinfo(H)
```

**References**

F.J. Harris (1978) On the Use of Windows for Harmonic Analysis with the Discrete Fourier Transform Proc. IEEE, 66, 51-53, 1978

D. Slepian (1978) Prolate Spheroidal Wave Functions. Fourier Analysis, and Uncertainty—V: The Discrete Case The Bell System Technical Journal,VoL 57, No. 5. May-June 1978

D.J. Thomson (1982) Spectrum estimation and harmonic analysis Proc. IEEE 70: 1055-1096, 1982.