How to find the maximum point of a fitted curve

조회 수: 41 (최근 30일)
Salma fathi
Salma fathi 2022년 10월 24일
댓글: Salma fathi 2022년 10월 25일
I am trying to find the maximum point of a fitted curve, the fitting method is being done using smoothing splines. I have looked around on how this can be done and found the following technique in the link below, which seems to be exactly what I am trying to do, except that I am getting a wrong output.
with reference to similar problem that I found in matlab answer in the link below
Now the output that I am getting is the attched plot where the maximum point appear to have a wrong location on the x-axis, is there any way to fix it or at least to figure out what is causing the issue?
attached below is the used code to generate the plot, I attach also a sample of the data used
function [fitresult, gof] = createFit3(x, y)
%% Fit: 'untitled fit 1'.
[xData, yData] = prepareCurveData( x, y );
% Set up fittype and options.
ft = fittype( 'smoothingspline' );
opts = fitoptions( 'Method', 'SmoothingSpline' );
opts.Normalize = 'on';
opts.SmoothingParam = 0.99602;
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
% Plot fit with data.
% figure( 'Name', 'untitled fit 1' );
plot( fitresult, xData, yData );
[ymax,xloc] = slmpar(coeffvalues(fitresult),'maxfun');
hold on
plot(xloc,ymax,'b*');
many thanks,
  댓글 수: 1
John D'Errico
John D'Errico 2022년 10월 24일
What was wrong with the result? (Since I wrote the SLM tools.)
Can I test your code? Of course not. We are not given the routine prepareCurveData. So how can I even test anything out?
MAYBE, that function just does
xdata = x;
ydata = y;
but how can I know?

댓글을 달려면 로그인하십시오.

채택된 답변

John D'Errico
John D'Errico 2022년 10월 24일
편집: John D'Errico 2022년 10월 24일
What was wrong with the result? (Since I wrote the SLM tools.)
Can I test your code? Of course not. We are not given the routine prepareCurveData. So how can I even test anything out?
MAYBE, that function just does
xdata = x;
ydata = y;
but how can I know? Perhaps I'll guess that is all it does, since the plot you show seems to be the same in fig1.fig.
Anyway, suppose I try that, trying to guess what you actually have..
ft = fittype( 'smoothingspline' );
opts = fitoptions( 'Method', 'SmoothingSpline' );
opts.Normalize = 'on';
opts.SmoothingParam = 0.99602;
% Fit model to data.
[fitresult, gof] = fit( x, y, ft, opts )
fitresult =
Smoothing spline:
fitresult(x) = piecewise polynomial computed from p
where x is normalized by mean 347.5 and std 88.74
Coefficients:
p = coefficient structure
Do you understand that fit returns a SPECIFIC form, from the curve fitting toolbox? Most importantly, READ THE MESSAGE YOU GOT. AND THINK ABOUT WHAT IT DID. Then you did this, without doing what I just said to do:
[ymax,xloc] = slmpar(coeffvalues(fitresult),'maxfun');
OF COURSE SLMPAR GIVES YOU SOMETHIGN STRANGE! You fed it something it was not designed to accept as input!!!!!!!
Why is there a problem? REREAD THE MESSAGE that fit returns.
where x is normalized by mean 347.5 and std 88.74
Coefficients:
So the curve fitting toolbox AUTOMATICALLY chose to shift and scale your data. The spline returned to you was:
coeffvalues(fitresult)
ans =
struct with fields:
form: 'pp'
breaks: [-1.6058 -1.4368 -1.2677 -1.0987 -0.92967 -0.76064 -0.59161 -0.42258 -0.25355 ]
coefs: [19×4 double]
pieces: 19
order: 4
dim: 1
Do you see that the breaks are NOT the vector of x values?
x'
ans =
Columns 1 through 16
205 220 235 250 265 280 295 310 325 340 355 370 385 400 415 430
Columns 17 through 20
445 460 475 490
Now look at what SLMPAR told you.
[ymax,xloc] = slmpar(coeffvalues(fitresult),'maxfun')
ymax =
1.5267e+12
xloc =
0.23313
So the maximum was correct. But the x location is not, and that is because you fed it a SHIFTED AND SCALED SPLINE! Can SLMPAR somehow magically know that fact? In fact, fit did not repair what it did, by unshifing and unscaling the spline. You needed to do that yourself. (Sorry, but that is just an unforgivable error on the part of the authors of fit. The code SHOULD make it possible to use the spline it returns! Worse, in order to extract the shift and scale parameters, I had to force them to be returned, using a call to struct.)
F = struct(fitresult);
Warning: Calling STRUCT on an object prevents the object from hiding its implementation details
and should thus be avoided. Use DISP or DISPLAY to see the visible public details of an object.
See 'help struct' for more information.
xloc*F.stdx + F.meanx
ans =
368.19
So that is the actual location of the maximum.
Plotting that point on the curve, we see;
plot( fitresult, x, y );
hold on
plot(xloc*F.stdx + F.meanx,ymax,'b*')
Don't say my code did not work. It does work, IF you use it as it should be used.
  댓글 수: 1
Salma fathi
Salma fathi 2022년 10월 25일
I never said your code didn't work, your code is a king. I only asked for help because I did not understand why I am getting such result. Now thank to you I understand. Appreciate all the help.

댓글을 달려면 로그인하십시오.

추가 답변 (1개)

Mathieu NOE
Mathieu NOE 2022년 10월 24일
hello
a simple and compact code that only uses this Fex submission
code
load('x&y.mat')
z = smoothn(y); % Regular smoothing
[ymax,idx] = max(z);
xloc = x(idx);
plot(xloc,ymax,'b*',x,y,'r.',x,z,'k','Markersize',20,'LineWidth',2)
result :
  댓글 수: 2
Salma fathi
Salma fathi 2022년 10월 24일
Thank you for your help, I tried whatyou suggetsed and it worked perfectly fine, but is the function you suggested using the usual smothing splines and not anything else, I am just trying to make sure here. And If you allow me to ask can we customize the fitting that this function offer as we do in the curve fitting toolbox (ex: to make the fitting rougher or smoother)? if yes would you please show me how?
Thanks a lot in advance.
Mathieu NOE
Mathieu NOE 2022년 10월 24일
hello again
yes there is a possibility to change the smoothing factor
load('x&y.mat')
z = smoothn(y); % Regular smoothing, S auto
zs = smoothn(y,4); % Regular smoothing, S used % Z = SMOOTHN(Y,S) smoothes the array Y using the smoothing parameter S.
[ymax,idx] = max(zs);
xloc = x(idx);
plot(xloc,ymax,'b*',x,y,'r.',x,z,'k',x,zs,'g','Markersize',20,'LineWidth',2)
legend('peak','data','smoothn auto','smoothn S = 4');

댓글을 달려면 로그인하십시오.

카테고리

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

제품


릴리스

R2022a

Community Treasure Hunt

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

Start Hunting!

Translated by