Fit gaussian to X-Y data (one X column, multiple Y column), for each Y column from an excel file.
18 views (last 30 days)
Show older comments
Titli
on 5 Apr 2024
Commented: Star Strider
on 4 Oct 2025 at 2:46
Hi, I want to fit gaussian curves to each Y column for an X-Y data set. I have ued cftool but I want to automatize the process which can give me FWHM values for each y column and also save the image of the fit so that I can see which fits are good and which are not. I can do these for each X-Y data one by one but not at once. I'll really appreciate any help.
2 Comments
Austin
on 3 Oct 2025 at 22:34
Hi! Can someone also help with a similar problem? I've been having a hard time trying to do a Gaussian Fit with these.
Star Strider
on 4 Oct 2025 at 2:46
Each oine of these (except 'Y2' that is just noise) has at least two peaks.
You can detect them with:
xy = [T1{:,1}, T1{:,k+1}];
[pksy,locsy] = findpeaks(xy(:,2), MinPeakProminence=0.01)
(refer to my original Answer for that context) and then fit each one using the code I provided in my original Answer.
That findpeaks call worked for all of the columns when i tried it with your data, and plotted the results.
This will require a second nested loop after the findpeaks call (use 'k1' for the outer loop counter and 'k2' for the inner nested loop counter) with the iterations of the inner loop controlled by the number of peaks or index locations returned by findpeaks for each column. Then fit each Gaussian separately.
I wrote code for this to fit the first Gaussian in each column (except 'Y2' as noted). I'll tweak it to fit the rest, just for my interest.
.
Accepted Answer
Star Strider
on 5 Apr 2024
Edited: Star Strider
on 5 Apr 2024
One approach —
T1 = readtable('X-Y_gauss_matlab.xlsx')
figure
plot(T1{:,1}, T1{:,2:end})
grid
gausfit = @(b,x) b(1) .* exp(-(x-b(2)).^2 .* b(3));
opts = optimset('MaxFunEvals',1E+5, 'MaxIter',1E+4);
for k = 1:size(T1,2)-1
xy = [T1{:,1}, T1{:,k+1}];
xy(~isfinite(xy)) = NaN;
xy = rmmissing(xy);
[col(:,k),nres(k)] = fminsearch(@(b) norm(xy(:,2) - gausfit(b,xy(:,1))), [1; 2; 1], opts);
idxrng = xy(:,1) <= col(2,k);
mp(1) = interp1(xy(idxrng,2), xy(idxrng,1), col(1,k)/2);
mp(2) = interp1(xy(~idxrng,2), xy(~idxrng,1), col(1,k)/2);
FWHM(k,:) = mp(2) - mp(1);
end
col
nres
tcol = [(2:size(T1,2)).' col.' FWHM nres(:)];
Results = array2table(tcol, 'VariableNames',{'Column','Height','Centre','Scale','FWHM','Res Norm'})
figure
tiledlayout(6,7)
for k = 1:size(col,2)
nexttile
plot(T1{:,1}, T1{:,k+1})
hold on
plot(T1{:,1}, gausfit(col(:,k),T1{:,1}))
hold off
grid
title("Column "+(k+1))
end
EDIT — (5 Apr 2024 at 13:37)
Added ‘opts’ to the fminsearch call, added ‘FWHM’.
.
2 Comments
More Answers (2)
xingxingcui
on 5 Apr 2024
Edited: xingxingcui
on 27 Apr 2024
HI,@Titli
You can export a function in the cftool APP to facilitate subsequent simultaneous manipulation of multiple variables.
For Example:
For Gaussian models, set up the various hyperparameters you need, and when your conditions are met, select the second option of the "export" button to export as a function.

function [fitresult, gof] = createFit(x, y1)
%CREATEFIT(X,Y1)
% 创建一个拟合。
%
% 要进行 '无标题拟合 1' 拟合的数据:
% X 输入: x
% Y 输出: y1
% 输出:
% fitresult: 表示拟合的拟合对象。
% gof: 带有拟合优度信息的结构体。
%
% 另请参阅 FIT, CFIT, SFIT.
% 由 MATLAB 于 05-Apr-2024 20:57:06 自动生成
%% 拟合: '无标题拟合 1'。
[xData, yData] = prepareCurveData( x, y1 );
% 设置 fittype 和选项。
ft = fittype( 'gauss1' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
opts.Display = 'Off';
opts.Lower = [-Inf -Inf 0];
opts.StartPoint = [1 2.048 0.375013106757709];
% 对数据进行模型拟合。
[fitresult, gof] = fit( xData, yData, ft, opts );
% 绘制数据拟合图。
figure( 'Name', '无标题拟合 1' );
h = plot( fitresult, xData, yData );
legend( h, 'y1 vs. x', '无标题拟合 1', 'Location', 'NorthEast', 'Interpreter', 'none' );
% 为坐标区加标签
xlabel( 'x', 'Interpreter', 'none' );
ylabel( 'y1', 'Interpreter', 'none' );
grid on
end
Finally, just use each X-Y data values in your script file to call the createFit function separately.
data = readmatrix("X-Y_gauss_matlab.xlsx");
x = data(:,1);
y1 = data(:,2);
createFit(x,y1)
for i = 2:size(data,2)
createFit(x,data(:,i))
end
-------------------------Off-topic interlude, 2024-------------------------------
I am currently looking for a job in the field of CV algorithm development, based in Shenzhen, Guangdong, China,or a remote support position. I would be very grateful if anyone is willing to offer me a job or make a recommendation. My preliminary resume can be found at: https://cuixing158.github.io/about/ . Thank you!
Email: cuixingxing150@gmail.com
Mathieu NOE
on 5 Apr 2024
coming late in the show
try this ...
if your data is "good" you can this this result , otherwise the fit may not allow any FWHM computation

% Importing Data from excel across multiple sheets.
filename = 'X-Y_gauss_matlab.xlsx';
T = readmatrix(filename,"NumHeaderLines",1); % X Y1 Y2 Y3 Y4 Y5 Y6 Y7 Y8 Y9 Y10 Y11 Y12 Y13 Y14 Y15 Y16 Y17 Y18 Y19 Y20 Y21 Y22 Y23 Y24 Y25 Y26 Y27 Y28 Y29 Y30 Y31 Y32 Y33 Y34 Y35 Y36 Y37
x = T(:,1);
for k= 1:size(T,2)-1
% Fitting data to a gaussian
yy = T(:,1+k);
yfit = my_gauss_fit(x,yy,x);
% FWHM computation (if possible)
threshold = max(yfit)/2;
[p1,p2] = find_zc(x,yfit,threshold);
if ~isempty(p1) & ~isempty(p2)
FWHM(k) = (p2-p1)
flag = 1;
else
FWHM(k) = NaN;
flag = 0;
end
figure(k)
plot(x,yy,'-',x,yfit, '-', 'LineWidth', 2);
if flag>0
hold on
plot([p1 p2],[threshold threshold],'r', 'LineWidth', 1);
plot(p1,threshold,'.r',p2,threshold,'.r', 'Markersize', 40);
text(p1*1.1,threshold*1.1,['FWHM = ' num2str(FWHM(k))]);
hold off
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function yfit = my_gauss_fit(x,y,xfit)
% Define g(x) = a*exp(-(x-mu)^2/(2*sigma^2)):
g = @(A,X) A(1)*exp(-(X-A(2)).^2/(2*A(3)^2));
%% ---Fit Data: Analitical Strategy---
% Cut Gaussian bell data
ymax = max(y); xnew=[]; ynew=[];
ind = y > 0.25*ymax;
xnew = x(ind);
ynew = y(ind);
% Fitting
ylog=log(ynew); xlog=xnew; B=polyfit(xlog,ylog,2);
% Compute Parameters
sigma=sqrt(-1/(2*B(1))); mu=B(2)*sigma^2; a=exp(B(3)+mu^2/(2*sigma^2));
% Plot fitting curve
A=[a,mu,sigma];
yfit = g(A,xfit);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [ZxP,ZxN] = find_zc(x,y,threshold)
% put data in rows
x = x(:);
y = y(:);
% positive slope "zero" crossing detection, using linear interpolation
y = y - threshold;
zci = @(data) find(diff(sign(data))>0); %define function: returns indices of +ZCs
ix=zci(y); %find indices of + zero crossings of x
ZeroX = @(x0,y0,x1,y1) x0 - (y0.*(x0 - x1))./(y0 - y1); % Interpolated x value for Zero-Crossing
ZxP = ZeroX(x(ix),y(ix),x(ix+1),y(ix+1));
% negative slope "zero" crossing detection, using linear interpolation
zci = @(data) find(diff(sign(data))<0); %define function: returns indices of +ZCs
ix=zci(y); %find indices of + zero crossings of x
ZeroX = @(x0,y0,x1,y1) x0 - (y0.*(x0 - x1))./(y0 - y1); % Interpolated x value for Zero-Crossing
ZxN = ZeroX(x(ix),y(ix),x(ix+1),y(ix+1));
end
See Also
Categories
Find more on Linear and Nonlinear Regression in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!