Fitting gaussian curve on my data with same under curve area and start and end points

조회 수: 4 (최근 30일)
I have a curve, as presented below. And want to fit a Gaussian curve on it, which has the same under curve area, start point, and end point. I would be appreciated if somebody let me know how I should do that?
The X and Y data are attached.

채택된 답변

Mathieu NOE
Mathieu NOE 2021년 9월 21일
hello
check this code (below)
plot
code
clc
clearvars
load Data_X.mat
load Data_Y.mat
x = Data_X;
y = Data_Y;
clear Data_X Data_Y
%% aera under data curve
y_area = trapz(x,y); % trapz integrates y with respect to the coordinates or scalar spacing specified by x.
%% define start / stop time points
threshold = 1e-3; % your value here
[t0_pos,s0_pos,t0_neg,s0_neg]= crossing_V7(y,x,threshold,'linear'); % positive (pos) and negative (neg) slope crossing points
% ind => time index (samples)
% t0 => corresponding time (x) values
% s0 => corresponding function (y) values , obviously they must be equal to "threshold"
%% gaussian pulse fit
% time center = mean of t0_pos and t0_neg
offset = 0.5*(t0_pos + t0_neg);
f0 = 6/(t0_neg - t0_pos); % frequency of the pulse to get 6 sigma into the time span between t0_pos and t0_neg (you can change from 6 to 3 to get a wider peak)
Var_Sq = 1; % pulse variance (squared) - default value - we will corect the amplitude below
signal_pulse = exp(-(((x-offset).^2).*(f0^2))./Var_Sq);
signal_pulse_area = trapz(x,signal_pulse); % aera under curve // trapz integrates y with respect to the coordinates or scalar spacing specified by x.
signal_pulse_amplitude_correction = y_area/signal_pulse_area;
signal_pulse = signal_pulse*signal_pulse_amplitude_correction;
signal_pulse_area = trapz(x,signal_pulse); % now we can see we have same area under curve as input data
figure(1)
plot(x,y,'b',x,signal_pulse,'r',t0_pos,s0_pos,'+k',t0_neg,s0_neg,'+g','linewidth',2,'markersize',12);grid on
legend('data','pulse signal','start point','stop point');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [t0_pos,s0_pos,t0_neg,s0_neg] = crossing_V7(S,t,level,imeth)
% [ind,t0,s0,t0close,s0close] = crossing_V6(S,t,level,imeth,slope_sign) % older format
% CROSSING find the crossings of a given level of a signal
% ind = CROSSING(S) returns an index vector ind, the signal
% S crosses zero at ind or at between ind and ind+1
% [ind,t0] = CROSSING(S,t) additionally returns a time
% vector t0 of the zero crossings of the signal S. The crossing
% times are linearly interpolated between the given times t
% [ind,t0] = CROSSING(S,t,level) returns the crossings of the
% given level instead of the zero crossings
% ind = CROSSING(S,[],level) as above but without time interpolation
% [ind,t0] = CROSSING(S,t,level,par) allows additional parameters
% par = {'none'|'linear'}.
% With interpolation turned off (par = 'none') this function always
% returns the value left of the zero (the data point thats nearest
% to the zero AND smaller than the zero crossing).
%
% check the number of input arguments
error(nargchk(1,4,nargin));
% check the time vector input for consistency
if nargin < 2 | isempty(t)
% if no time vector is given, use the index vector as time
t = 1:length(S);
elseif length(t) ~= length(S)
% if S and t are not of the same length, throw an error
error('t and S must be of identical length!');
end
% check the level input
if nargin < 3
% set standard value 0, if level is not given
level = 0;
end
% check interpolation method input
if nargin < 4
imeth = 'linear';
end
% make row vectors
t = t(:)';
S = S(:)';
% always search for zeros. So if we want the crossing of
% any other threshold value "level", we subtract it from
% the values and search for zeros.
S = S - level;
% first look for exact zeros
ind0 = find( S == 0 );
% then look for zero crossings between data points
S1 = S(1:end-1) .* S(2:end);
ind1 = find( S1 < 0 );
% bring exact zeros and "in-between" zeros together
ind = sort([ind0 ind1]);
% and pick the associated time values
t0 = t(ind);
s0 = S(ind);
if ~isempty(ind)
if strcmp(imeth,'linear')
% linear interpolation of crossing
for ii=1:length(t0)
%if abs(S(ind(ii))) > eps(S(ind(ii))) % MATLAB V7 et +
if abs(S(ind(ii))) > eps*abs(S(ind(ii))) % MATLAB V6 et - EPS * ABS(X)
% interpolate only when data point is not already zero
NUM = (t(ind(ii)+1) - t(ind(ii)));
DEN = (S(ind(ii)+1) - S(ind(ii)));
slope = NUM / DEN;
slope_sign(ii) = sign(slope);
t0(ii) = t0(ii) - S(ind(ii)) * slope;
s0(ii) = level;
end
end
end
% extract the positive slope crossing points
ind_pos = find(sign(slope_sign)>0);
t0_pos = t0(ind_pos);
s0_pos = s0(ind_pos);
% extract the negative slope crossing points
ind_neg = find(sign(slope_sign)<0);
t0_neg = t0(ind_neg);
s0_neg = s0(ind_neg);
else
% empty output
ind_pos = [];
t0_pos = [];
s0_pos = [];
% extract the negative slope crossing points
ind_neg = [];
t0_neg = [];
s0_neg = [];
end
end

추가 답변 (0개)

카테고리

Help CenterFile Exchange에서 Interpolation에 대해 자세히 알아보기

제품


릴리스

R2020b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by