0
$\begingroup$

I have data that looks like this:

Data

When I try to fit a Gaussian to it, it obviously tries to fit the first peak, like so:

Bad Fit

This fit was found using

ff = FindFit[data, a*Exp[-(x - b)^2/(2*c^2)] + d, {a, b, c, d}, x]

This isn't what I want. The huge peak on the left should be ignored because it's due to "irrelevant artifacts." However, when I try to make it just ignore the first ~400 points, I get a fit that's even more unhelpful: Worse fit

I got this by editing my previous code slightly:

ff = FindFit[Take[data,-1648], a*Exp[-(x - b)^2/(2*c^2)] + d, {a, b, c, d}, x]

I'm not sure what to do that will fit only the smaller peak on the right-hand side. I have some success if I adjust the data such that the y values of all the data points between 0 and 400 are equal to some constant (roughly between 600 and 1000), but the value of that constant changes the fit parameters and I don't know how to find the right constant without brute-forcing it, and I'm not even sure if that's the right thing to be doing here. Any advice would be much appreciated!

$\endgroup$
2
  • 1
    $\begingroup$ With your second example, try guesses for a and b, like {a,5000} and {b,1100}. $\endgroup$ Commented Feb 8, 2019 at 21:49
  • $\begingroup$ That about does it, thanks so much! $\endgroup$ Commented Feb 8, 2019 at 22:07

1 Answer 1

1
$\begingroup$

It would be good if you included some sample data. Anyway...

The fit function does not magically find your small points of interest in a long list of data points ;) you need to first tell it where to look, and then it might be necessary to also provide some reasonable starting values for the fit. Also, the fitting algorithm will work globally on your full data set, which is not what you want, especially not for e.g. meaurements where you might have considerable noise or background data around the peak that you want to fit.

You need to constrain it to fit around the peak, which you can either do by simply not including unnecessary data, and/or by putting some reasonable initial values, e.g.

truncatedData=data[[500;;1500]];
ff = FindFit[truncatedData, 
     a*Exp[-(x - b)^2/(2*c^2)] + d, 
     {{a,Max[truncatedData]},{b,Position[truncatedData,Max[truncatedData]][[1,1]]},
         c, d}, x]

Now I put in the ranges 500 to 1500 manually, and they might need to be adjusted. Unless your data is always very similar, it would be best to define these ranges automatically. If you e.g. know that a peak is never longer than 300 data points, and the initial peak that you want to exclude is always within the first 400 data points, you could use:

peakPos = Position[data[[400;;-1]],Max[data[[400;;-1]]]][[1,1]]+399;
lowerLim = peakPos-150;
upperLim = peakPos+150;
truncatedData = data[[lowerLim;;upperLim]]

If however these secondary peaks that you want to fit can be very different, you need to apply something smarter for finding the limits. You could e.g. use the Select function to select all values above your noise baseline, find the position of them using the Position function, and then use these for the lower and upper limits.

$\endgroup$

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