I have the data which appears like
And I decided to use three Gaussian curves to fit it.
(This code allows me to manipulate all three curves and put in best guesses for peak positions. Using these guesses, Mathematica will find a set of three gaussian curves that are the closest match if one clicks click find nearest solution
.)
\[Lambda]min=340;
\[Lambda]max=380;
model = height + amp1*Exp[-(x - x01)^2/sigma1^2] + amp2*Exp[-(x - x02)^2/sigma2^2] + amp3*Exp[-(x - x03)^2/sigma3^2]
findBestFitFromValues[{amp1guess_, x01guess_, sigma1guess_,
amp2guess_, x02guess_, sigma2guess_, amp3guess_, x03guess_,
sigma3guess_, heightguess_}] :=
FindFit[
rowData(*change this*), {model, {sigma1 > 0, sigma2 > 0, sigma3 > 0}}, {{amp1,
amp1guess}, {x01, x01guess}, {sigma1, sigma1guess}, {amp2,
amp2guess}, {x02, x02guess}, {sigma2, sigma2guess}, {amp3,
amp3guess}, {x03, x03guess}, {sigma3, sigma3guess}, {height,
heightguess}}, x];
With[
{
localModel =
model /.
{
amp1 -> amp1Var, amp2 -> amp2Var, amp3 -> amp3Var,
sigma1 -> sigma1Var, sigma2 -> sigma2Var, sigma3 -> sigma3Var,
x01 -> x01Var, x02 -> x02Var, x03 -> x03Var,
height -> heightVar
}},
Manipulate[
Column[{
Style["Match to Data", 12, Bold],
Show[rowDataPlot(*change this*),
Plot[localModel, {x, 1240/\[Lambda]max, 1240/\[Lambda]min},
PlotRange -> All, PlotStyle -> Black] ,Graphics[
{
Orange,Line[{{x01Var,0}, {x01Var,500}}],
Blue,Line[{{x02Var,0}, {x02Var,500}}],
Red,Line[{{x03Var,0}, {x03Var,500}}]
}
]],
Style["Chosen Curve", 12, Bold],
Plot[localModel, {x, 1240/\[Lambda]max, 1240/\[Lambda]min},
PlotRange -> All, PlotStyle -> Black, ImageSize -> 400]}
],
Delimiter, Style["Peak 1", 12, Bold],
{{amp1Var, 2000, Style["Amplitude 1", Orange]}, 0, 40000},
{{x01Var,
1240/\[Lambda]min - (1240/\[Lambda]min - 1240/\[Lambda]max) 1/5,
Style["center 1", Orange]}, 1.95, 3.6},
{{sigma1Var, 0.01, Style["sigma 1", Orange]}, 0.01, 0.3},
Delimiter, Style["Peak 2", 12, Bold],
{{amp2Var, 1660, Style["Amplitude 2", Blue]}, 0, 15000},
{{x02Var,
1240/\[Lambda]min - (1240/\[Lambda]min - 1240/\[Lambda]max) 2/5,
Style["center 2", Blue]}, 1.95, 3.6},
{{sigma2Var, 0.01, Style["sigma 2", Blue]}, 0.01, 0.3},
Delimiter, Style["Peak 3", 12, Bold],
{{amp3Var, 1445, Style["Amplitude 3", Red]}, 0, 10000},
{{x03Var,
1240/\[Lambda]min - (1240/\[Lambda]min - 1240/\[Lambda]max) 4/5,
Style["center 3", Red]}, 1.95, 3.6},
{{sigma3Var, 0.01, Style["sigma 3", Red]}, 0.01, 0.3},
Delimiter, Style["Height", 12, Bold],
{{heightVar, 15, Style["Height"]}, 0, 1000},
Delimiter,
Control[Button["click find nearest solution",
vals =
{amp1Var, x01Var, sigma1Var, amp2Var, x02Var, sigma2Var, amp3Var,
x03Var, sigma3Var,
heightVar} = {amp1, x01, sigma1, amp2, x02, sigma2, amp3, x03,
sigma3, height} /.
findBestFitFromValues[
{amp1Var, x01Var, sigma1Var, amp2Var, x02Var, sigma2Var,
amp3Var, x03Var, sigma3Var, heightVar}]]],
SaveDefinitions -> True
]
]
If I want to fit another data with four or more Gaussian curves, how can I re-write my code to obtain the curve fitting that I can specify the number of Gaussian curves? Not the above one where I constrain the number to be three.
EDIT1
I mean, if I specify the number n to be 2, then we can have a two-Gaussian-curve fitting panel, if I specify the number n to be 3, then we can have a three-Gaussian-curve fitting panel,
Locator
's to define the individual Gaussian-shaped curves? ALocator
at the peak of the curve could define the height and central value. ALocator
on the "side" of the Gaussian curve could be restricted to move horizontally to vary the width. Sliders are good for when you have a "numerical" idea as to the values of the parameters. Here you want the user to set a "visual" idea as to the values of the parameters. This would also make the display less crowed. $\endgroup$