Complex signal low pass filter

I'm trying to implement a low pass filter in python for a complex signal but the output doesn't look right. I've created a simple example below where I've mixed a 15Hz complex sine wave and a 30Hz complex sine wave so that I get a signal with components (30+15=45Hz and 30-15=15Hz).

What I'm trying to do is filter this signal with a low pass filter to just give the resultant 15Hz component. When I look at the plot of the filtered signal though the imaginary component seems to be almost identical (same phase) as the real signal. It doesn't look right.

Example of code to reproduce then plot below:

import numpy as np
import matplotlib.pyplot as plt
from scipy.signal import butter, lfilter
import scipy.signal as sig

#Sample rate.
rate = 5000

# Create a 15 Hz comlex signal.
t = np.arange(0,5000)/rate
f1 = 15
msg =  np.exp(1j* (2*np.pi * f1 * t))

# Create a 30 Hz complex signal.
f2 = 30
bb_lo = np.exp(1j * (2*np.pi * f2 * t))

# Create a low pass filter to remove the upper frequency.
nyq = 0.5 * rate
cut = 30
low = cut / nyq
b, a = sig.butter(5, low, btype='low')

# Mix the low frequency and high frequency signal together.
# Will result in a signal with freq components of f1+f2 and f2 - f1.
# Then apply the filter to real and imaginary parts.
signalFilt = lfilter(b,a , bb_lo.real*msg.real) + 1j*lfilter(b,a , bb_lo.imag*msg.imag)

plt.plot(signalFilt.real)
plt.plot(signalFilt.imag)
plt.grid()
plt.show()


Frequency filter looks right at approx 15Hz but real/imaginary in plot I don't think should be the same. What am I doing wrong here? Thanks

• I've mixed a 15Hz complex sine wave and a 30Hz complex sine wave so that I get a signal with components (30+15=45Hz and 30-15=15Hz).. No, you don't. These aren't sine or cosine, which have positive and negative frequency components, they are a complex exponential with only exactly one frequency component, so you only get the sum frequency. – Marcus Müller Aug 30 '20 at 17:31

You're not actually mixing two complex exponentials, because otherwise you'd get a complex exponential with the sum of the frequencies of the individual complex exponentials. That was already mentioned in a comment by Marcus Müller.

What you are doing is compute a signal with real part $$\cos(\omega_0t)\cos(\omega_1t)$$ and with imaginary part $$\sin(\omega_0t)\sin(\omega_1t)$$. If you lowpass filter that signal, only the components with the difference of the two frequencies remain, but these components are the same for the real and for the imaginary part, because

$$\cos(\omega_0t)\cos(\omega_1t)=\frac12\big[\cos[(\omega_0-\omega_1)t]+\cos[(\omega_0+\omega_1)t]\big]\tag{1}$$

and

$$\sin(\omega_0t)\sin(\omega_1t)=\frac12\big[\cos[(\omega_0-\omega_1)t]-\cos[(\omega_0+\omega_1)t]\big]\tag{2}$$

Clearly, the components with the difference frequency are the same.

Also, if you want to filter out a component with frequency $$\omega_x$$ (in your case the component with the sum frequency), it is not wise to use a filter with cut-off frequency $$\omega_c=\omega_x$$ because the attenuation at $$\omega_c$$ is usually quite modest, in your case $$3$$dB. Choose a frequency that is much closer to the lower frequency component to get a decent attenuation of the higher frequency component.

• Thanks - so if I've understood correctly I should have done: signalFilt = lfilter(b,a , bb_lo*msg) to mix the two signals (as exponentials). However, when I look at the output of the low pass filter it isn't a 15Hz wave when multiplied like that? – user1759872 Aug 30 '20 at 19:52
• Re-reading I suppose that is Marcus comment that only the positive frequency exists. I suppose I'm confused now as I thought exp(i THETA) = cos(THETA) + i sin(THETA) – user1759872 Aug 30 '20 at 20:01
• The following question answers my above comments: dsp.stackexchange.com/questions/4825/why-is-the-fft-mirrored – user1759872 Aug 30 '20 at 20:15