def low_pass_gauss_filter(n, sigma_filter): lg.function_log() lg.text_log('filtering high frequencies - defined by sigma') x = np.arange(0, n, 1) return (np.exp(-(x**2) * 0.5 / sigma_filter**2) + np.exp(-(((x - n + 1)**2) * 0.5 / sigma_filter**2)))
def iDFT(x_d): """Compute the inverse discrete Fourier Transform of the 1D array x""" x_d = np.asarray(x_d) N = x_d.shape[0] j = np.arange(N) k = j.reshape((N, 1)) W_1 = np.exp(2j * np.pi * j * k / N) lg.text_log('iDFT calculation via matrix multiplication') return 1 / N * np.dot(W_1, x_d)
def DFT(x): """Compute the discrete Fourier Transform of the 1D array x""" x = np.asarray(x) N = x.shape[0] j = np.arange(N) k = j.reshape((N, 1)) W = np.exp(-2j * np.pi * j * k / N) lg.text_log('DFT calculation via matrix multiplication') return np.dot(W, x)
def fourier_params(dt, I, frequency=None, plot=None): #calculate fourier transform f_range, spectrum = fourier_transform(dt, I) #get values from fourier transform lg.text_log('get values from fourier transform') magnitude_list = np.multiply(np.abs(spectrum), (1 / (len(spectrum) + 1))) phase_list = np.angle(spectrum) real_list = np.real(spectrum) imag_list = np.imag(spectrum) #optional plots if plot == 'magnitude': plt.plot(f_range, magnitude_list) if plot == 'phase': plt.plot(f_range, phase_list) if plot == 'real': plt.plot(f_range, real_list) if plot == 'imag': plt.plot(f_range, imag_list) #get index of highest magnitude value lg.text_log( 'get parameters for defined frequency or frequency with highest magnitude' ) if frequency == None: mag_sort_indices = np.argsort(magnitude_list) f_index = mag_sort_indices[-1] else: diff_f = [abs(f_i - frequency) for f_i in f_range] f_index = [list(diff_f).index(x) for x in diff_f if x == min(diff_f)][0] #get corresponding values for highest magnitude frequency = f_range[f_index] magnitude = magnitude_list[f_index] phase = phase_list[f_index] real = real_list[f_index] imag = imag_list[f_index] return frequency, magnitude, phase, real, imag
def fourier_transform(dt, I): """ Calculates discrete or fast fourier transform. Depends on signal array size Parameters ---------- dt : float signal time point distance. I : list or array signal intensity array. Returns ------- f_range : numpy array frequency range. spectrum : numpy array complex fourier coefficients. """ exp = np.log(len(I)) / np.log(2) lg.text_log( 'compute discrete or fast fourier transform, depending on signal array size' ) if exp.is_integer(): lg.text_log('numpy fast fourier transform (CT Algorithm)') F_I = np.fft.fft(I) else: F_I = DFT(I) lg.text_log( 'calculate frequency increment: f_inc = 1/(n_f*2*dt) with dt: time delta and n_f number of timepoints/2' ) n_f = int(len(F_I) / 2) f_inc = 1 / (n_f * 2 * dt) lg.text_log('frequency spectrum without aliased frequencies is returned') spectrum = F_I[1:(n_f)] f_range = np.arange(1 * f_inc, f_inc * n_f, f_inc) return f_range, spectrum
def baseline(dt, I, report=True, logfile=None): """ Parameters ---------- dt : float; distance between time points. I : array; Signal Intensity/Magnitude. Returns ------- baseline : List; Intensity array for baseline subtraction. inclination : float; inclination of baseline calculated via linear regression. """ lg.function_log() #create spectrum to analyze lg.text_log('calculate fourier transform') f_range, spectrum = fourier_transform(dt, I) lg.text_log('get magnitude from spectrum') magnitude = gauss_optimum(np.abs(spectrum)) lg.text_log('get extrema of fourier transform magnitude') max_x, max_y, min_x, min_y = lg.var_log(find_extrema(f_range, magnitude)) lg.text_log('get cutoff frequency - at first minimum') bg_cutoff = lg.var_log( min((min_x[np.argsort(min_y)[-1]]), (max_x[np.argsort(max_y)[-1]]))) lg.text_log('get indices below cutoff') bg_indices = lg.var_log( [list(f_range).index(x) for x in f_range if x < bg_cutoff]) lg.text_log('maximum index*0.5 yields sigma for gauss filtering ') sigma_filter = lg.var_log(max(bg_indices) / 2) #create full spectrum for filtering and inverse fourier transformation full_spectrum = DFT(I) #create gauss filter gauss_filter = np.asarray( low_pass_gauss_filter(len(full_spectrum), sigma_filter)) #filter spectrum by multiplication with gauss filter filtered_spectrum = np.multiply(full_spectrum, gauss_filter) normalized_magnitude = np.multiply(np.abs(full_spectrum[1:]), 1 / max(np.abs(full_spectrum[1:]))) lg.img_log((normalized_magnitude, gauss_filter[1:]), title='gauss filter', plot='yn', legend=['raw spectrum', 'gauss_fiter'], x_axis='n', y_axis='magnitude') #create baseline via inverse fourier transformation baseline = np.abs(iDFT(np.asarray(filtered_spectrum))) t = np.arange(0, len(I) * dt, dt) coef = np.polyfit(t, baseline, 1) inclination = coef[0] poly1d_fn = np.poly1d(coef) lg.img_log((t, (I, baseline, poly1d_fn(t))), title='baseline calculation', legend=['raw signal', 'fourier filtering baseline', 'line fit'], x_axis='t [s]', y_axis='I A.U.') return baseline, inclination