cutcutcodec.core.signal.window

Window a signal to control gib effects.

The only window coded here is the optimal dpss window. Thanks to its parameterization, it can be used in a general case to find the optimum compromise between frequency accuracy and noise on secondary lob.

Functions

alpha_to_att(alpha)

Empirical estimation based on regression.

alpha_to_band(alpha)

Empirical estimation based on regression.

att_to_alpha(att)

Inverse of the empirical estimation based on regression.

band_to_alpha(band)

Inverse of the empirical estimation based on regression.

dpss(nb_samples, alpha[, dtype])

Compute the Discrete Prolate Spheroidal Sequences (DPSS).

find_dpss_law([nb_samples, nb_alphas])

For each beta parameter, associate the frequency properties.

Details

cutcutcodec.core.signal.window.alpha_to_att(alpha: float) float[source]

Empirical estimation based on regression.

The fitted model is (attenuation = a*alpha + b + c*tanh(d*alpha)).

Examples

>>> import torch
>>> from cutcutcodec.core.signal.window import find_dpss_law
>>> alphas, atts, _ = find_dpss_law()
>>> alphas, atts = alphas.to(torch.float64), atts.to(torch.float64)
>>> abcd = torch.tensor([3.393, 9.292, 271.5, 0.06323], dtype=torch.float64, requires_grad=True)
>>> optim = torch.optim.Adam([abcd])
>>> for _ in range(10000):
...     pred = abcd[0]*alphas + abcd[1] + abcd[2]*torch.tanh(abcd[3]*alphas)
...     optim.zero_grad()
...     torch.mean((atts - pred)**2).backward()
...     optim.step()
...
>>> abcd.detach().to(torch.float32)
tensor([3.3538e+00, 9.2918e+00, 2.7240e+02, 6.3155e-02])
>>> # import matplotlib.pyplot as plt
>>> # _ = plt.plot(alphas.numpy(force=True), atts.numpy(force=True))
>>> # _ = plt.plot(alphas.numpy(force=True), pred.numpy(force=True))
>>> # plt.show()
>>>
cutcutcodec.core.signal.window.alpha_to_band(alpha: float) float[source]

Empirical estimation based on regression.

The fitted model is \(band = a*\alpha + b + c*tanh(d*\alpha)\).

This function is close to the identity function.

Examples

>>> import torch
>>> from cutcutcodec.core.signal.window import find_dpss_law
>>> alphas, _, bands = find_dpss_law()
>>> alphas, bands = alphas.to(torch.float64), bands.to(torch.float64)
>>> abcd = torch.tensor([0.932, 0.815, -0.559, 1.61], dtype=torch.float64, requires_grad=True)
>>> optim = torch.optim.Adam([abcd])
>>> for _ in range(10000):
...     pred = abcd[0]*alphas + abcd[1] + abcd[2]*torch.tanh(abcd[3]*alphas)
...     optim.zero_grad()
...     torch.mean((bands - pred)**2).backward()
...     optim.step()
...
>>> abcd.detach().to(torch.float32)
tensor([ 0.9321,  0.8148, -0.5588,  1.6099])
>>> # import matplotlib.pyplot as plt
>>> # _ = plt.plot(alphas.numpy(force=True), bands.numpy(force=True))
>>> # _ = plt.plot(alphas.numpy(force=True), pred.numpy(force=True))
>>> # plt.show()
>>>
cutcutcodec.core.signal.window.att_to_alpha(att: float) float[source]

Inverse of the empirical estimation based on regression.

The inverse function is based on the tangent.

Examples

>>> from cutcutcodec.core.signal.window import alpha_to_att, att_to_alpha
>>> round(alpha_to_att(att_to_alpha(20.0)), 4)
20.0
>>> round(alpha_to_att(att_to_alpha(40.0)), 4)
40.0
>>> round(alpha_to_att(att_to_alpha(80.0)), 4)
80.0
>>> round(alpha_to_att(att_to_alpha(120.0)), 4)
120.0
>>> round(alpha_to_att(att_to_alpha(160.0)), 4)
160.0
>>>
cutcutcodec.core.signal.window.band_to_alpha(band: float) float[source]

Inverse of the empirical estimation based on regression.

The inverse function is based on the tangent.

Examples

>>> from cutcutcodec.core.signal.window import alpha_to_band, band_to_alpha
>>> round(alpha_to_band(band_to_alpha(0.9)), 4)
0.9
>>> round(alpha_to_band(band_to_alpha(1.8)), 4)
1.8
>>> round(alpha_to_band(band_to_alpha(3.4)), 4)
3.4
>>> round(alpha_to_band(band_to_alpha(4.9)), 4)
4.9
>>> round(alpha_to_band(band_to_alpha(6.4)), 4)
6.4
>>>
cutcutcodec.core.signal.window.dpss(nb_samples: Integral, alpha: Real, dtype=torch.float64) Tensor[source]

Compute the Discrete Prolate Spheroidal Sequences (DPSS).

It is similar to the scipy function scipy.signal.windows.dpss.

Parameters

nb_samplesint

The window size, it has to be >= 3.

alphafloat

Standardized half bandwidth.

dtypetorch.dtype, default=float64

The data type of the window samples: torch.float64 or torch.float32.

Returns

windowtorch.Tensor

The 1d symetric window, normalized with the maximum value at 1.

Examples

>>> import torch
>>> from cutcutcodec.core.signal.window import dpss
>>> dpss(1024, 2.0)
tensor([0.0158, 0.0163, 0.0169,  ..., 0.0169, 0.0163, 0.0158],
       dtype=torch.float64)
>>>
>>> # comparison with kaiser
>>> alpha, nbr = 5.0, 129
>>> win_dpss = dpss(nbr, alpha)
>>> win_kaiser = torch.kaiser_window(
...     nbr, periodic=False, beta=alpha*torch.pi, dtype=torch.float64
... )
>>> gain_dpss = 20*torch.log10(abs(torch.fft.rfft(win_dpss, 100000)))
>>> gain_dpss -= torch.max(gain_dpss)
>>> gain_kaiser = 20*torch.log10(abs(torch.fft.rfft(win_kaiser, 100000)))
>>> gain_kaiser -= torch.max(gain_kaiser)
>>>
>>> # import matplotlib.pyplot as plt
>>> # fig, (ax1, ax2) = plt.subplots(2)
>>> # _ = ax1.plot(win_dpss, label="dpss")
>>> # _ = ax1.plot(win_kaiser, label="kaiser")
>>> # _ = ax1.legend()
>>> # _ = ax2.plot(torch.linspace(0, 0.5, 50001), gain_dpss, label="dpss")
>>> # _ = ax2.plot(torch.linspace(0, 0.5, 50001), gain_kaiser, label="kaiser")
>>> # _ = ax2.axvline(x=alpha/nbr)
>>> # _ = ax2.legend()
>>> # plt.show()
>>>
cutcutcodec.core.signal.window.find_dpss_law(nb_samples: Integral = 129, nb_alphas: Integral = 1000) tuple[Tensor, Tensor, Tensor][source]

For each beta parameter, associate the frequency properties.

Parameters

nb_samplesint, default=65

The window size, it has to be >= 3.

nb_alphasint, default=1000

The number of alpha points.

Returns

alphastorch.Tensor

The apha values.

attstorch.Tensor

The real positive attenuation of the secondaries lobs in dB.

bandstorch.Tensor

The normalised size of the main lob.

Examples

>>> import torch
>>> from cutcutcodec.core.signal.window import find_dpss_law
>>> alphas, atts, bands = find_dpss_law()
>>>
>>> # import matplotlib.pyplot as plt
>>> # _ = plt.plot(alphas.numpy(force=True), atts.numpy(force=True), label="attenuation")
>>> # _ = plt.plot(alphas.numpy(force=True), bands.numpy(force=True), label="band")
>>> # _ = plt.legend()
>>> # plt.show()
>>>