0

this is my first post so I apologize for any noob mistakes.

I've been trying to fit what is essentially a 1+cos function to my data using the code:

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
from numpy.polynomial import polynomial as p
from scipy.signal import find_peaks

def FP_cavity_ref(x, coeff, L):
    R1 = 0.035
    R2 = 0.003
    n = 1.0003
    Amp = p.polyval(x, coeff)
    phi = ((4*np.pi*L*n)/x)+np.pi

    func = Amp*(R1+R2+2*np.sqrt(R1*R2)*np.cos(phi))/(1+R1*R2+2*np.sqrt(R1*R2)*np.cos(phi))
    return func/np.max(func)

def cav_len_calc(raw_data):
    spec = np.asarray([raw_data])
    peaks, _ = find_peaks(raw_data)
    peak_intensity = raw_data[peaks]
    c, stats = p.polyfit(xval[peaks], peak_intensity, 8, full=True)
    coeffs = c

    param, pconv = curve_fit(lambda xval, L: FP_cavity_ref(xval, coeffs, L), xval, raw_data, p0=177000)

    y = FP_cavity_ref(xval, coeffs, param)

    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.plot(xval, raw_data, label='Raw data')
    ax.plot(xval, y, label='Fit')
    ax.set_xlabel('Wavelength (nm)', fontsize=14)
    ax.set_ylabel('Intensity (a.u.)', fontsize=14)
    handles, labels = ax.get_legend_handles_labels()
    ax.legend(fontsize=12)
    plt.show()

    return

xval = np.linspace(1280, 1330, 300)

cav_len_calc()

This essentially produces this plot:

Output plot

I've managed to get the wavelength dependent amplitude sorted using a polynomial fit obtained from peak finding however I am at a loss on how to get the valleys of the fitted data to match the raw data while still keeping the peaks correct.

Is there a way to do this in python?

William Miller
  • 9,839
  • 3
  • 25
  • 46
  • Welcome to StackOverflow, I think it is better for you to give some data example (maybe some sine with a noise) to help with the error reproducibility. – iury simoes-sousa Mar 20 '20 at 16:45
  • What kind of fit are you trying to do? Sine fit, fourier? – iury simoes-sousa Mar 20 '20 at 16:49
  • For sine fit you can use this: https://stackoverflow.com/questions/16716302/how-do-i-fit-a-sine-curve-to-my-data-with-pylab-and-numpy – iury simoes-sousa Mar 20 '20 at 16:50
  • Thank you for the response. I'm trying to fit a 1 + cos(phi), where phi = 4* pi * cavity_length * refractive index / wavelength. It is data from project where I have created an optical fibre Fabry-Perot interferometer. The problem with my data is that the amplitude varies with wavelength which appears to cause the curve_fit function some issues – Fellowhuman Mar 20 '20 at 17:25
  • I couldn't go though all your code, but this result is kind of strange. You are getting the low frequency signal, and it seems it is getting right for the upper part, but not for the lower part. I don't think it is just the case of amplitude changing with wavelength. The error seems to be constant for all the troughs. – iury simoes-sousa Mar 20 '20 at 21:25
  • It seems that if you multiply and subtract some factor you gonna get match the fit product with the data. So it seems the parameters you are getting from curve_fit is not exactly the same parameters you are looking for. You should revise your fitting. – iury simoes-sousa Mar 20 '20 at 21:29
  • If you correct the fit product by the difference between the average from the two series, you probably gonna see that the error in the amplitude is kind of constant. – iury simoes-sousa Mar 20 '20 at 21:31

0 Answers0