Tapers
Tapers are an important part of multitapering. They are used both to reduce bias from edge effects, and to reduce variance by providing "pseudo-replications". In SpatialMultitaper
, there are a number of dedicated structs to represent the notion of a taper, as well as many convnience functions to create them. It is important to distinguish between tapers for continuous processes, and tapers for discrete processes. However, we shall begin the description for the continuous case, as one can often subsample these to obtain legitimate discrete tapers. See the mathematical background and developer notes for more information.
Creating tapers on a box
If the region of interest is a box, then one can easily extend a family of univariate tapers by taking the family of their cross products. One dimensional families on the unit interval are easily extended to a general interval. In particular, say that we have a taper $\tilde h:[0,1]\rightarrow \mathbb{R}$, then we may define $h:[a,b]\rightarrow \mathbb{R}$ by $h(x) = \tilde h((x-a)/(b-a)) / \sqrt{b-a}$. The simplest family of continuous tapers on a box are the sin tapers [5].
SpatialMultitaper.sin_taper_family
— Functionmake_sin_tapers(lbw, region::Box, gridsize)
Construct the sin tapers for a given region and gridsize.
Arguments:
ntapers
: The number of tapers.region
: The region to construct the tapers on. Must be a box.
Background:
The sin tapers on a unit interval are defined as:
\[h_m(x) = \sqrt{2} * \sin(πxm)\]
Creating tapers on arbitrary regions
using SpatialMultitaper
import GLMakie as Mke
We can also construct families of tapers for other regions of interest, using the methodology proposed by [6]. For example, say we are interested in an octagonal region
c = 0.3
region = PolyArea([
(0, 1 - c), (c, 1), (1 - c, 1), (1, 1 - c), (1, c), (1 - c, 0), (c, 0), (0, c)
])
viz(region)

We can construct discrete tapers for this region using the make_taper
function:
tapers, concentrations = make_tapers(region, bandwidth = 3.5);
tapers
A family of 12 taper functions.
In this case, we obtain 12 well concentrated tapers within this bandwidth. We can visualize the tapers:
fig = Mke.Figure()
ax = [Mke.Axis(fig[i, j], aspect = 1) for i in 1:3, j in 1:4]
for i in eachindex(tapers)
Mke.heatmap!(ax[i], range(0, 1, 100), range(0, 1, 100),
(x, y) -> tapers[i](x, y), colorrange = (-3, 3))
viz!(ax[i], boundary(region), color = :black)
end
Mke.Colorbar(fig[:, end + 1], colorrange = (-3, 3))
Mke.hidedecorations!.(ax)
fig

Note that this process can be slow for complex regions, or if high resolution grids are used.
SpatialMultitaper.make_tapers
— Functionmake_tapers(region; bandwidth, threshold = 0.99, space_res = 100, wavenumber_res = 500, wavenumber_generate_res = 500, ntapers_max = 30)
A function to create tapers for a given region.
Arguments
region
: The region to create the tapers on.bandwidth
: The bandwidth of the tapersthreshold
: The threshold for the number of tapers to use.space_res
: The resolution of the grid to create the tapers on.wavenumber_res
: The resolution of the wavenumber grid to compute the transfer function on.wavenumber_generate_res
: The resolution of the wavenumber grid to generate the tapers on.ntapers_max
: The maximum number of tapers to generate.
As a rough rule of thumb, setting the bandwidth to an integer multiple (say x
) of a side length of the bounding square of a region will produce x^d
tapers (note this is a very crude approximation, but you will find out how many good tapers you can make when you create them).
Exploring the tapers
Given a constructed family of tapers, one can index into them to obtain one single taper.
taper = tapers[1]
A continuous interpolated taper function.
We can evaluate the taper at a given point by calling it as a function:
taper(0.5, 0.5)
3.693029358212823
Alternatively, we can pass a point or a tuple
taper(Point(0.5, 0.5))
taper((0.5, 0.5))
3.693029358212823
We can also consider the Fourier transform of the taper, which is a function of wavenumber. In general, we would like the Fourier transform to be well concentrated around the origin, and to decay quickly away from it. When constructing the general tapers, we specified a bandwidth, within which we expect the Fourier transform to be well concentrated (in a ball around zero with a radius of the bandwidth). We can evaluate the Fourier transform of the taper at a given wavenumber with the taper_ft
function:
taper_ft(taper, 0, 0)
0.5144531617759792 + 0.0im
So plotting the abs2
of Fourier transforms to check the concentrations we see that
fig = Mke.Figure()
ax = [Mke.Axis(fig[i, j], aspect = 1) for i in 1:3, j in 1:4]
for i in eachindex(tapers)
Mke.heatmap!(ax[i], range(-5, 5, 100), range(-5, 5, 100),
(x, y) -> abs2(taper_ft(tapers[i], x, y)))
viz!(ax[i], boundary(Ball(Point(0, 0), 3.5)), color = :white)
end
Mke.hidedecorations!.(ax)
fig

Mathematical background
Developer notes
References
- [5]
- K. S. Riedel and A. Sidorenko. Minimum bias multiple taper spectral estimation. IEEE Transactions on Signal Processing 43, 188–195 (1995).
- [6]
- F. J. Simons and D. V. Wang. Spatiospectral concentration in the Cartesian plane. GEM-International Journal on Geomathematics 2, 1–36 (2011).
This page was generated using Literate.jl.