I'm coding with python and I just started to use the Hilbert transform from scipy.signal. Consequently, to check the result I got I tried to verify a property of the Hilbert transform:

$H(H(\vec{x})) = -\vec{x}$

So I implemented the following code:

import numpy as np
from scipy.signal import hilbert

# my input vector, an 1D numpy array of real numbers
x = ... 

# I consider the imaginary part here as scipy.hilbert
# returns the analytical signal computed with the
# Hilbert transform (imaginary part).
x_ = hilbert(hilbert(x).imag).imag 

However I can't retrieve x_ == -x.

Do you know what this could be due to?

Here are plots of x and x_ (first figure) and the difference (second figure): plot of x and x_

plot of the difference between x and x_

  • $\begingroup$ Can you include what you are using for x specifically? $\endgroup$ May 9, 2020 at 11:38
  • $\begingroup$ It looks like to me your data is approximately constant, is that true? The Hilbert Transform really only applies to time varying signals. Subtract the mean of your signal to only have a time varying signal and you may get what you expect. $\endgroup$ May 9, 2020 at 13:59
  • $\begingroup$ The beginning of the sample doesn't vary much but then there is a peak with a big variation. I will try to ubstract the mean to see if it changes anything $\endgroup$
    – Rhecsu
    May 9, 2020 at 14:13
  • $\begingroup$ No, the results are still very different even after substracting the mean value $\endgroup$
    – Rhecsu
    May 9, 2020 at 14:15
  • $\begingroup$ It might be illuminating if you posted a figure showing x and x_. $\endgroup$
    – Matt L.
    May 9, 2020 at 18:21

2 Answers 2


It looks like it's working fine, but your signal contains some content at DC and the Nyquist frequency. DC doesn't survive through the transform, and Nyquist gets altered. If you bandlimit it first, it will work out as expected:

import numpy as np
from scipy.signal import hilbert, butter, sosfilt
import matplotlib.pyplot as plt

r = np.random.rand(100)
bp = butter(10, [0.1, 0.9], 'bp', output='sos', fs=2)
x = sosfilt(bp, r)
plt.plot(x, label="x")

x_ = -hilbert(hilbert(x).imag).imag
plt.plot(x_, label="-H(H(x))")
  • $\begingroup$ Yes it worked after using a bandlimit indeed, thank you very much $\endgroup$
    – Rhecsu
    May 10, 2020 at 10:43

What you did should work, up to a constant, as mentioned by Dan Boschen in a comment. The Hilbert transform will remove any DC component, so the output of the second Hilbert transform should equal the (negative of the) input, up to a constant, and, of course, up to numerical accuracy.

The following example (in Octave) shows this:

t = 0:1024;
x = sin(pi/7*t)+3*cos(pi/5*t);    % some signal
xh = imag( hilbert(x) );
xhh = imag( hilbert(xh) );
err = x - mean(x) + xhh;
max( abs(err) )                   % 6.2172e-15
  • $\begingroup$ It actually works with your function but not with my data, it may come fome the fact my values doesn't vary much as mentionned by Dan Boschen even if I substracted the mean value $\endgroup$
    – Rhecsu
    May 9, 2020 at 20:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.