1

I want to fit a gaussian to a curve using python . I found a solution here somewhere but it only seems to work for an n shaped gaussian , not for a u shaped gaussian .

Here is the code:

import pylab, numpy

from scipy.optimize import curve_fit

x=numpy.array(range(10))

y=numpy.array([0,1,2,3,4,5,4,3,2,1])

n=len(x)

mean=sum(y)/n

sigma=sum(y-mean)**2/n

def gaus(x,a,x0,sigma):
    return a*numpy.exp(-(x-x0)**2/(2*sigma**2))

popt, pcov=curve_fit(gaus,x,y,p0=[1,mean,sigma])

pylab.plot(x,y,'r-',x,y,'ro')

pylab.plot(x,gaus(x,*popt),'k-',x,gaus(x,*popt),'ko')

pylab.show()

The code fits a gaussian to an n shaped curve but if I change y to y=numpy.array([5,4,3,2,1,2,3,4,5,6]) then it return some error: Optimal parameters not found: Number of calls to function has reached maxfev = 800.

What do I have to change/adjust in the code to fit a U shaped gaussian ? Thanks.

Christian Tapia
  • 33,620
  • 7
  • 56
  • 73
Kantura
  • 5,763
  • 5
  • 18
  • 17
  • Are you sure this is your actual code? When I run this, I get a `RuntimeWarning` due to division by 0, since `sigma` is 0 (you probably want `numpy.sqrt(sum((y-mean)**2)/n)` if that's supposed to be a standard deviation). – senshin Jan 14 '14 at 06:03
  • Hi senshin . Yes above is my actual code . It works for the n shape . – Kantura Jan 14 '14 at 08:16

2 Answers2

3

The functional form of your fit is wrong. Gaussian's are expected to go to 0 at the tails regardless of whether it is an n or u shape, but yours goes to ~5.

If you introduce an offset into your equation, and choose reasonable initial values, it works. See code below:

import pylab, numpy
from scipy.optimize import curve_fit

x=numpy.array(range(10))
y=numpy.array([5,4,3,2,1,2,3,4,5,6])

n=len(x)
mean=sum(y)/n
sigma=sum(y-mean)**2/n

def gaus(x,a,x0,sigma,c):
    return a*numpy.exp(-(x-x0)**2/(2*sigma**2))+c

popt, pcov=curve_fit(gaus,x,y,p0=[-1,mean,sigma,-5])

pylab.plot(x,y,'r-',x,y,'ro')
pylab.plot(x,gaus(x,*popt),'k-',x,gaus(x,*popt),'ko')
pylab.show()
three_pineapples
  • 11,579
  • 5
  • 38
  • 75
  • I am now trying to fit a U shaped gaussian to a curve with min(x)=7250 , max(x)=7849 , min(y)=2.4*10^-16 , max(y)=4.3*10^-16 I've been playin garound with values for the c constant but I just end up with a straight line . What should I use in this case ? – Kantura Jan 14 '14 at 08:10
  • for `c`, you need something around `-max(y)` if it is u shaped. However the problem is likely the initial guess of `a` which is far bigger than the amplitude of your Gaussian. Try setting `a ~= -2E-16` (negative is for u shaped gaussian, and the magnitude of `a` is approx the difference between min(y) and max(y)) – three_pineapples Jan 14 '14 at 08:59
1

Perhaps you could invert your values, fit to a 'n' shaped gaussian, and then invert the gaussian.

Madison May
  • 2,723
  • 3
  • 22
  • 32