# Hilbert transform with scipy.signal

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):

• Can you include what you are using for x specifically? May 9, 2020 at 11:38
• 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. May 9, 2020 at 13:59
• 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 May 9, 2020 at 14:13
• No, the results are still very different even after substracting the mean value May 9, 2020 at 14:15
• It might be illuminating if you posted a figure showing x and x_. May 9, 2020 at 18:21

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))")
plt.legend()

• Yes it worked after using a bandlimit indeed, thank you very much 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

• 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 May 9, 2020 at 20:03