I have this 7 quasi-lorentzian curves which are fitted to my data.

enter image description here

and I would like to join them, to make one connected curved line. Do You have any ideas how to do this? I've read about ComposingModel at lmfit documentation, but it's not clear how to do this.

Here is a sample of my code of two fitted curves.

for dataset in [Bxfft]:
    dataset = np.asarray(dataset)
    freqs, psd = signal.welch(dataset, fs=266336/300, window='hamming', nperseg=16192, scaling='spectrum')
    plt.semilogy(freqs[0:-7000], psd[0:-7000]/dataset.size**0, color='r', label='Bx')
    x = freqs[100:-7900]
    y = psd[100:-7900]

    # 8 Hz
    model = Model(lorentzian)
    params = model.make_params(amp=6, cen=5, sig=1, e=0)
    result = model.fit(y, params, x=x)
    final_fit = result.best_fit
    print "8 Hz mode"
    plt.plot(x, final_fit, 'k-', linewidth=2)

    # 14 Hz
    x2 = freqs[220:-7780]
    y2 = psd[220:-7780]

    model2 = Model(lorentzian)
    pars2 = model2.make_params(amp=6, cen=10, sig=3, e=0)
    pars2['amp'].value = 6
    result2 = model2.fit(y2, pars2, x=x2)
    final_fit2 = result2.best_fit
    print "14 Hz mode"
    plt.plot(x2, final_fit2, 'k-', linewidth=2)

What I desire is something like this.

enter image description here

| cite | improve this question | | | | |
  • 1
    $\begingroup$ I have an example of fitting a double Lorentzian peak equation to Raman spectroscopy of carbon nanotubes at bitbucket.org/zunzuncode/RamanSpectroscopyFit -that might be a useful starting point for you to build on as the problem is somewhat similar. $\endgroup$ – James Phillips Jun 1 '18 at 19:23
  • 1
    $\begingroup$ Thanks for uploading, well it's quite useful, but my problem is that for every curve I change my initial x (which is data), and looking at your example there are two lorentzians, but they are based on the same sample of data. $\endgroup$ – Hiddenguy Jun 1 '18 at 20:02

That pretty much solved my problem.

    x = freqs[100:-7240]
    y = psd[100:-7240]

    peak1 = Model(lorentzian, prefix='p1_')
    peak2 = Model(lorentzian, prefix='p2_')
    peak3 = Model(lorentzian, prefix='p3_')
    peak4 = Model(lorentzian, prefix='p4_')
    peak5 = Model(lorentzian, prefix='p5_')
    peak6 = Model(lorentzian, prefix='p6_')
    peak7 = Model(lorentzian, prefix='p7_')

    # make composite by adding (or multiplying, etc) components
    model = peak1 + peak2 + peak3 + peak4 + peak5 + peak6 + peak7

    # make parameters for the full model, setting initial values
    # using the prefixes
    params = model.make_params(p1_amp=6, p1_cen=8, p1_sig=1, p1_e=0,
                               p2_amp=16, p2_cen=14, p2_sig=3, p2_e=0,
                               p3_amp=16, p3_cen=21, p3_sig=3, p3_e=0,
                               p4_amp=16, p4_cen=28, p4_sig=3, p4_e=0,
                               p5_amp=16, p5_cen=33, p5_sig=3, p5_e=0,
                               p6_amp=16, p6_cen=39, p6_sig=3, p6_e=0,
                               p7_amp=16, p7_cen=45, p7_sig=3, p7_e=0)

    # then do a fit over the full data range
    result = model.fit(y, params, x=x)
    final = result.best_fit
    plt.plot(x, final, 'k-', linewidth=2)
| cite | improve this answer | | | | |
  • 1
    $\begingroup$ Sometime you can get a better fit by adding an offset parameter - that might be useful in the future. $\endgroup$ – James Phillips Jun 4 '18 at 1:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.