Radvin
Radvin

Reputation: 163

Fitting data with multiple Gaussian profiles in Python

I have some data (data.txt) and am trying to write a code in Python to fit them with Gaussian profiles in different ways to obtain and compare the peak separation and the under curve area in each case:

  1. with two Gaussian profiles (considering the little peaks on top and ignoring the shoulders; the red profiles)
  2. with two Gaussian profiles (ignoring the little peaks on top and considering the whole single peak at top and the shoulders; the black profiles)
  3. with three Gaussian profiles (considering a tall peak on the two shorter ones in the shoulders; the green profiles)

I tried several scripts, but I failed in all.

The profiles in these plots are fake, and I just added them to illustrate better what I mean.

plots

Upvotes: 1

Views: 8653

Answers (2)

Jon Nordby
Jon Nordby

Reputation: 6289

scikit-learn has an implementation of GaussianMixtureModel, it can do this. See the user guide for examples.

Upvotes: 0

tikker
tikker

Reputation: 236

One approach to this is as follows:

  1. Define the function you want to fit to the data, i.e. the sum of all components that should be in there. In your case this is multiple Gaussians.
  2. Find initial guesses for your parameters.
  3. Fit your fitting function to the data, using a strategy to your liking.

I took a go at your data, and below is a very simple example of fitting for three Gaussian components and a continuum offset, using SciPy's curve_fit method. I'll leave the rest to you. This should allow you to figure out the other cases as well. Note that initial guesses generally are important, so it's best to make an educated guess somehow, to get as close to the optimal value as possible.

Code

from scipy.optimize import curve_fit

import matplotlib.pyplot as plt
import numpy as np

def gaussian(x, A, x0, sig):
    return A*np.exp(-(x-x0)**2/(2*sig**2))

def multi_gaussian(x, *pars):
    offset = pars[-1]
    g1 = gaussian(x, pars[0], pars[1], pars[2])
    g2 = gaussian(x, pars[3], pars[4], pars[5])
    g3 = gaussian(x, pars[6], pars[7], pars[8])
    return g1 + g2 + g3 + offset

vel, flux = np.loadtxt('data.txt', unpack=True)
# Initial guesses for the parameters to fit:
# 3 amplitudes, means and standard deviations plus a continuum offset.
guess = [4, -50, 10, 4, 50, 10, 7, 0, 50, 1]
popt, pcov = curve_fit(multi_gaussian, vel, flux, guess)

plt.figure()
plt.plot(vel, flux, '-', linewidth=4, label='Data')
plt.plot(vel, multi_gaussian(vel, *popt), 'r--', linewidth=2, label='Fit')
plt.legend()
plt.show()

Result

Three-Gaussian fit

Upvotes: 3

Related Questions