I'm trying to simulate a Fourier transform spectrometer in Python. I started basically with a simple single frequency (f=1e10 Hz) sine signal coming into the spectrometer. I obtained the following plot of the signal against time:
What the spectrometer is measuring is only the intensity of this signal - that is, the field amplitude squared. I plotted the field amplitude against frequency, so what I should obtain on my detector:
Now I did the inverse Fourier of my intensity and plotted the amplitude of my obtained signal against time:
As you can see, I fitted the signal that I obtained, and I don't get back the frequency that I settled at the beginning, so my code is not working. I don't understand why.
Here is my code (it's quite long I'm sorry but I'm stuck.):
import numpy as np
import matplotlib.pyplot as plt
import cmath
import scipy #for integral
from scipy.integrate import quad #for integral of kinf function f(x) between range a and b over x
from scipy import optimize
from scipy.fft import fft, fftfreq
# define constants
c = 3 * 10e8 # m/s, c = omega / k
#define variables
f = 10e9 #Hz
phi = 0 # phase à l'origine en rad (souvent fixée par l'expérimentateur)
# set the frequency range over which the integral will be calculated
f_min = 1e9
f_max = 500e9
# number of sample
N = 1000
#sample maximal value
M = 8e-9 # in s
#samples spacing
S = M / N # 1/s
# define time range
time_range = np.linspace(1/f_max, 1/f_min, N)
#create an array of the signal as a function of time
signal_in_time = 1 * np.sin(f * time_range + phi)
# plot of the signal of frequency w against time
plt.figure(figsize=(10,4))
plt.plot(time_range, signal_in_time, color = 'b', label ='f = {:.1e} Hz'.format(f))
plt.xlabel('Time [s]')
plt.ylabel('Field amplitude [V/m]')
plt.title('Field amplitude of the signal against time')
plt.legend(loc='upper right')
plt.grid()
# store this signal in an array of signal measured at every frequency: there is only one signal at frequency w
field_amplitude = np.zeros(N)
# define frequency range
frequency_range = np.linspace(f_min, f_max, N)
# store this signal at the slice of the array of corresponding ferquency
j=0
for i in frequency_range:
#print('{:e}'.format(i))
#print(i)
if i == 9990990990.990992:
print('BINGO')
field_amplitude[j] = sin
j += 1
else:
j += 1
#print(field_amplitude)
# in this cell, do the inverse Fourier transform of the Field versus angular frequency array
# array of intensity: here just square of amplitude array
intensity = field_amplitude * field_amplitude
#inverse Fourier of the intensity
inv_four = np.fft.ifft(intensity)
# define the x axis for the plot of the signal
time_range = np.linspace(1/500e9, 1/1e9, N)
# Plot of the Intensity (inverse Fourier transform of the incident power) versus time
plt.figure(figsize=(8,4))
plt.plot(time_range, inv_four.real, '+-', color = 'b', label = 'Inverse Fourier transform')
plt.xlabel('Time [s]')
plt.ylabel('Intensity [W]')
plt.title('Measured signal in time domain')
plt.ticklabel_format(useMathText=True)
plt.xlim(np.min(time_range), np.max(time_range))
plt.grid()
plt.legend(loc='center left', bbox_to_anchor=(0, -0.22))
plt.show()
#define a sinus function to fit the measured signal
def sin_fit(x, a, b, c):
return a * np.sin(b * x + c)
# sin = 1 * np.sin(f * 1e-9 + phi)
# do the fit
params, params_covariance = optimize.curve_fit(sin_fit, time_range, inv_four.real, p0=[0.0003, 11.3e+10, +0.9])
a = params[0]
b = params[1]
c = params[2]
print('the parameters found by the fits are: ', params)
print('Angular frequency of the signal that is set: {:2e}'.format(f))
print('Angular frequency found by Fourier transform: {:2e}'.format(b))
# Plot of the Intensity (inverse Fourier transform of the incident power) versus time
plt.figure(figsize=(8,4))
plt.plot(time_range, inv_four.real, '+-', color = 'b', label = 'Inverse Fourier transform')
plt.plot(time_range, sin_fit(time_range, a, b, c), '-', color = 'r', label = 'Fit: y = {:.2e}'.format(a) +'sin({:.2e} * t'.format(b) + ' + {:.2})'.format(c))
#plt.plot(time_range, sin_fit(time_range, 0.0003,11.3e+10, +0.9), color = 'orange')
plt.xlabel('Time [s]')
plt.ylabel('Intensity [W]')
plt.title('Measured signal in time domain')
plt.ticklabel_format(useMathText=True)
plt.xlim(np.min(time_range), np.max(time_range))
plt.grid()
plt.legend(loc='center left', bbox_to_anchor=(0, -0.22))
plt.show()