BUG: scipy.fft.dct type I with norm = "ortho" leads to wrong powers in modes
See original GitHub issueDescribe your issue.
Applying the type I DCT yields to confusing/wrong results. If norm = “backward”, the individual modes k=0pi, 1pi, … contain the right amount of energy according to the input signal. However, using norm = “ortho”, the power in the individual modes of the transform does not correspond any more to the original signal (see code snippet 1). This is a critical bug.
I traced the issue down to the normalisation. The misbehaviour is caused by the modification of the input signal (see documentation of SciPy DCT (x[0], x[N-1])) before performing the transform. Thus, the DCT result does not correspond any more to the original signal.
I am aware that one might argue that this bug exists only to make Parseval’s theorem hold directly from the input signal and the DCT. However, this is definitely secondary as then the actual DCT result is malicious.
I suggest that the DCT type I result should contain the power in modes of the original input signal, and not of the modified one. The scaling of y[k] (see documentation of SciPy DCT) can still be applied in case of norm = “ortho”. After this fix, the documentation should mention that Parseval’s theorem only holds if one scales/weights the input signal as indicated by the scaling of x[0], x[N-1] in the current documentation.
The problem and its solution is also discussed in a StackOverflow question: https://stackoverflow.com/questions/69946957/scipy-discrete-cosine-transform-dct-power-in-non-existing-frequencies
Reproducing Code Example
### code snippet 1
import numpy as np
x = np.linspace(0, 1, 8, endpoint = True)
f = np.cos(1 * np.pi * x)
import scipy.fft
f_DCT = scipy.fft.dct(f, type = 1, norm = "ortho")
# f_DCT:
# array([ 3.35699888e-16, 2.09223516e+00, -1.48359792e-17, 2.21406462e-01,
# -1.92867730e-16, 2.21406462e-01, 1.18687834e-16, 1.56558011e-01])
# One expects power only at k=1pi, but here there is power in many other modes too.
Error message
None
SciPy/NumPy/Python version information
1.6.2 1.20.2 sys.version_info(major=3, minor=8, micro=8, releaselevel=‘final’, serial=0)
Issue Analytics
- State:
- Created 2 years ago
- Comments:6 (3 by maintainers)
That’s right, it’s typically given for Fourier transforms and especially considering the proper extension of the signal. Maybe it’s asked for too much to consider this special case of supporting the theorem even for “half” signals in this standard library.
My use case is the following: I want to analyse 3d flow data in a Cartesian domain which is periodic in horizontal directions only. I cannot simply add the flow domain in reverse order on top to make the domain fully periodic (and use then DFTs only), as this will change the kz=0 mode. Thus, DCTs and DSTs are necessary. To make sure that both descriptions (physical and “Fourier” space) coincide, I typically check Parseval’s theorem by means of the variance of the signal and the “Fourier” coefficients. When this holds, one is able to directly analyse quantities from physical space by the use of the coefficients with all its advantages (filtering scales).
Strictly speaking I think Parseval’s theorem only applies to the fourier transform, so you would need to consider the even extension of the input signal. If you do that, then the normalization I gave is correct because some elements appear multiple times in the summation.
Perhaps it would make sense if you explained your use case?