How do I find initial point of an exponential graph given a set of data points?
3 views (last 30 days)
Show older comments
I have a noisy signal imported from a 24k x 1 excel sheet that was passed through a guassian filter to smooth out the curves as seen below.

What i need to find is the initial point in which the graph starts to turn exponentially as seen below, denoted as the black x.

I tried findchangepoints however, it gives me the red x as shown in the pictures as it only marks the points with the highest change.
ChangePts = findchangepts(graph,'Statistic','linear','MaxNumChanges',2);
Anybody knows any functions or methods that i should look into to solve this?
Edit: Just added the data.mat file. Kept forgetting to do so, sorry guys for the trouble.
11 Comments
Rik
on 5 Nov 2021
It will make matters easier if you post your data in a mat file. Feel free to attach it to your question so it doesn't get burried in the comments.
Accepted Answer
Mathieu NOE
on 5 Nov 2021
hello
sorry, i'm coming late in the show
this is my result and the code below , using the second derivative, smoothing and threshold crossing detection
hope it helps

clc
clearvars
S = load('data.mat');
x = S.CropTime_1;
dx = mean(diff(x));
y = S.Crop_yggaus_D1_3;
dyg = gradient(y,dx);
ddyg = gradient(dyg,dx);
ddygs = smoothdata(ddyg,'gaussian',200);
% [pks,locs] = findpeaks(ddygs,'MinPeakHeight',max(ddygs)/2,'NPeaks',2);
threshold = max(ddygs)/20;
[t0_pos1,s0_pos1,t0_neg1,s0_neg1]= crossing_V7(ddygs,x,threshold,'linear'); % positive (pos) and negative (neg) slope crossing points
x1 = t0_pos1(1);
x2 = t0_neg1(end);
y1 = interp1(x,y,x1);
y2 = interp1(x,y,x2);
figure(1)
subplot(211),plot(x,y,x1,y1,'*r',x2,y2,'+c','linewidth',2,'markersize',12);
subplot(212),plot(x,ddygs,t0_pos1,s0_pos1,'*r',t0_neg1,s0_neg1,'+c','linewidth',2,'markersize',12);grid on
legend('second derivative','positive slope crossing points','negative slope crossing points');
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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
4 Comments
More Answers (0)
See Also
Categories
Find more on Spline Postprocessing 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!







