I have a irregular set of data points in the form of cartesian coordinates which using the MATLAB cftool can be turned into a surface (see below).
Does anyone know a way to access the matrix of cartesian coordinates that MATLAB generates in order for it to plot this surface?
The code generated for this graph (seen below) provides no access to the any additional interpolated points which must be produced to fit the surface.
%% Fit: 'untitled fit 1'.
[xData, yData, zData] = prepareSurfaceData( x1, y1, z1 );
% Set up fittype and options.
ft = 'linearinterp';
% Fit model to data.
[fitresult, gof] = fit( [xData, yData], zData, ft, 'Normalize', 'on' );
% Plot fit with data.
figure( 'Name', 'untitled fit 1' );
h = plot( fitresult, [xData, yData], zData );
legend( h, 'untitled fit 1', 'z1 vs. x1, y1', 'Location', 'NorthEast' );
% Label axes
xlabel x1
ylabel y1
zlabel z1
grid on
Thanks in advance
As a possible workaround (potentially not very efficient) is to plot the output of the fit (fitresult) and fetch the XData, YData and ZData properties of the plotted surface.
For example, after performing a dummy fit:
hP = plot(fitresult)
yields those properties for hP:
Surface (curvefit.gui.FunctionSurface) with properties:
EdgeColor: [0 0 0]
LineStyle: '-'
FaceColor: 'flat'
FaceLighting: 'flat'
FaceAlpha: 1
XData: [51x49 double]
YData: [51x49 double]
ZData: [51x49 double]
CData: [51x49 double]
So you can retrieve them.
ALTERNATIVE
as an alternative, you could use the code generated by cftool to provide additional output arguments to the function (called createFit or somethinbg like this). Therefore, as you call the function with enough arguments you will obtain those coordinates directly.
Example:
change the header of the generated function like so:
[fitresult, gof,a,b,c] = createFit1(x, y, z)
and then in the function body:
a = xData;
b = yData;
c = zData;
then calling the function in the Command Window, for example, yields the right coordinates in a,b and c.
Related
I have an extremely basic question seeking to answer why the following function in MatLab does not properly fit the given data to a logistic curve, given the correct equation for one. The solution to this is likely quite simple, but I am entirely unfamiliar with the MatLab curve fitting toolbox. My code is as follows:
function [fitresult, gof] = createFit1(Dose, Response)
%CREATEFIT1(DOSE,RESPONSE)
% Create a fit.
%
% Data for 'untitled fit 1' fit:
% X Input : Dose
% Y Output: Response
% Output:
% fitresult : a fit object representing the fit.
% gof : structure with goodness-of fit info.
%
% See also FIT, CFIT, SFIT.
% Auto-generated by MATLAB on 08-Sep-2022 20:16:26
%% Fit: 'untitled fit 1'.
Dose = [1.6*10^4;1.84*10^4;2.08*10^4;2.32*10^4; 2.56*10^4;2.8*10^4;3.04*10^4;3.28*10^4;3.52*10^4;3.76*10^4;4*10^4;4.24*10^4]
Response = [0;0.1004;0.2830;0.4338;0.5638;0.6834;0.8030;0.8680;0.9294;0.9614;0.9978;1]
[xData, yData] = prepareCurveData( Dose, Response );
% Set up fittype and options.
ft = fittype( '1/(1+exp(-k*Dose))', 'independent', 'Dose', 'dependent', 'Response' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
opts.Display = 'Off';
opts.StartPoint = 0.0755269568571602;
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
% Plot fit with data.
figure( 'Name', 'untitled fit 1' );
h = plot( fitresult, xData, yData );
legend( h, 'Response vs. Dose', 'untitled fit 1', 'Location', 'NorthEast', 'Interpreter', 'none' );
% Label axes
xlabel( 'Dose', 'Interpreter', 'none' );
ylabel( 'Response', 'Interpreter', 'none' );
grid on
They are probably two causses of bad fitting.
First : Obviously the points are not located close to a simple logistic curve but close to a shifted logistic curve. So, it is suggested to change the model equation in your code.
Second : The non-linear regression is an iterative process requiring to set some guessed initial values of parameters. If the initial values are too far from the unknown exact values the calculus might fail to achieve a good fit.
If you don't know how to guess some initial values of the parameters better use a not iterative method which doesn't requires initial values as shown below.
Numerical example with your data :
If you want to use your non-linear regression software you can use the above good approximates of the parameters to initiate the iterative process.
An even better fitting would be obtained with a not only horizontal shift (horizontal and vertical shifts).
For information on the non-iterative method used above (linear fitting of an integral equation to which the logistic function is solution ) : https://fr.scribd.com/doc/14674814/Regressions-et-equations-integrales .
In addition : FOUR PARAMETERS LOGISTIC CURVE FITTING
I used matlab's CFtool to generate a fit based on a custom function, however, when I generate that code and call it to my main script file the curves are slightly different. My generated code does not cross the y -int, although it does in CFtool. Does any body know what the issue is? I have tried setting different start points and it didn't change anything.
Suggestions
Generated code:
%% Fit: 'untitled fit 1'.
[xData, yData] = prepareCurveData( I100M, P100M );
% Set up fittype and options.
ft = fittype( 'a*tanh(-b*x/300)+c', 'independent', 'x', 'dependent', 'y' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
opts.Display = 'Off';
opts.StartPoint = [0.990128346443291 0.106912965297856 0.94637904214048];
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
% Plot fit with data.
figure( 'Name', 'untitled fit 1' );
h = plot( fitresult, xData, yData );
CFtool fit
generated code
Having 2 vectors vec_x and vec_y, i perform a fitting with a non-linear least squares like this :
%%myfunction.m
function F = myfun(x,vec_x)
F = 10*(erfc((x(1)+x(2)*vec_x)/sqrt(2))/2);
end
%%console
options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt');
x = lsqcurvefit(#myfun, [0 1], vec_x, vec_y,[],[],options); %here i obtain x(1) and x(2).
When i want to plot the fitting curve with the associated points(vec_x .vs vec_y), i perform it like this :
y_fit=10*erfc((x(1)+x(2)*vec_x)/sqrt(2))/2
plot(vec_x,y_fit)
The problem is that i have a weird curve not similar to the one i have automatically when i'm using the "Curv-fit App" tool of Matlab (i use the same custom function and vectors as the console).
In the Curve-fitting GUI, i got this : see the image below
snapshot-curveFitting-GUI
How can i have the right plot so i can more mange the plot ?
I found the answer on the doc of Matlab. For plotting the curve fit from the Cftool, we should select File->Generate code. The Curve Fitting app generates code from the current session and displays the file in the MATLAB Editor. The file includes all fits and plots in the current session. We have to execute the code to have the plot.
this is the code that was generated by Matlab:
function [fitresult, gof] = createFit_MSSI_Venus(RockerArm, mos)
%CREATEFIT1(ROCKERARM,MOS)
% Create a fit.
%
% Data for 'Psychometric curve fitting MSSI-RockeArm 3D mesh' fit:
% X Input : RockerArm
% Y Output: mos
% Output:
% fitresult : a fit object representing the fit.
% gof : structure with goodness-of fit info.
%
% See also FIT, CFIT, SFIT.
% Auto-generated by MATLAB on 08-Jan-2016 15:40:41
%% Fit: 'Psychometric curve fitting MSSI-RockeArm 3D mesh'.
[xData, yData] = prepareCurveData( RockerArm, mos );
% Set up fittype and options.
ft = fittype( 'erfc((a+b*x)/sqrt(2))/2', 'independent', 'x',
'dependent', 'y' );
opts = fitoptions( 'Method', 'NonlinearLeastSquares' );
opts.Algorithm = 'Levenberg-Marquardt';
opts.Display = 'Off';
opts.StartPoint = [0.655477890177557 0.171186687811562];
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
% Plot fit with data.
figure( 'Name', 'Psychometric curve fitting MSSI-RockeArm 3D mesh' );
h = plot( fitresult, xData, yData);
set(h, 'Markersize',20);
legend( h, 'mos vs. RockerArm', 'Psychometric curve fitting MSSI-
RockeArm 3D mesh', 'Location', 'NorthEast' );
% Label axes
xlabel MSSI-RockerArm 3D mesh
ylabel mos
grid on
Thanks again
I used the MATLAB curve fitting tool to do a spline smoothing fit and created a function from it. How can I access the Y fit values so I can output them to a file? Seems I am only seeing the x values, and all of the coefs from fitresult. Here is the matlab code. Thanks!
function [fitresult, gof] = createFit(Freq, AmplNew)
%CREATEFIT(FREQ,AMPLNEW)
% Create a fit.
%
% Data for 'untitled fit 1' fit:
% X Input : Freq
% Y Output: AmplNew
% Output:
% fitresult : a fit object representing the fit.
% gof : structure with goodness-of fit info.
%
%% Fit: 'untitled fit 1'.
[xData, yData] = prepareCurveData( Freq, AmplNew );
% Set up fittype and options.
ft = fittype( 'smoothingspline' );
opts = fitoptions( 'Method', 'SmoothingSpline' );
opts.SmoothingParam = 0.998;
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
Simply use feval:
y = feval(fitresult,x);
or just use
y = fitresult(x);
I am using Matlab's curve fitting tool, cftool, to fit a set of points which I have. The problem I am facing is that the generate code function will not give me the same fit as produced in the cftool.
This is not what I want because I want to be able to retrieve the data from the residual plot. I could also just copy the function from cftool and do it manually. But I do not understand why the generated code will not just give me the same curve fit.
The cftool session file: http://dl.dropbox.com/u/20782274/test.sfit
The generated code from Matlab:
function [fitresult, gof] = createFit1(Velocity, kWhPerkm)
%CREATEFIT1(VELOCITY,KWHPERKM)
% Create a fit.
%
% Data for 'untitled fit 3' fit:
% X Input : Velocity
% Y Output: kWhPerkm
% Output:
% fitresult : a fit object representing the fit.
% gof : structure with goodness-of fit info.
%
% See also FIT, CFIT, SFIT.
% Auto-generated by MATLAB on 02-Dec-2012 16:36:19
%% Fit: 'untitled fit 3'.
[xData, yData] = prepareCurveData( Velocity, kWhPerkm );
% Set up fittype and options.
ft = fittype( 'a/(0.008*x) + c*x^2 + d*90', 'independent', 'x', 'dependent', 'y' );
opts = fitoptions( ft );
opts.DiffMaxChange = 0.01;
opts.Display = 'Off';
opts.Lower = [-Inf -Inf -Inf];
opts.MaxFunEvals = 1000;
opts.MaxIter = 1000;
opts.StartPoint = [0 0 0];
opts.Upper = [Inf Inf Inf];
% Fit model to data.
[fitresult, gof] = fit( xData, yData, ft, opts );
% Create a figure for the plots.
figure( 'Name', 'untitled fit 3' );
% Plot fit with data.
subplot( 2, 1, 1 );
plot( fitresult, xData, yData, 'predobs' );
% Label axes
xlabel( 'Velocity' );
ylabel( 'kWhPerkm' );
grid on
% Plot residuals.
subplot( 2, 1, 2 );
plot( fitresult, xData, yData, 'residuals' );
% Label axes
xlabel( 'Velocity' );
ylabel( 'kWhPerkm' );
grid on
The curve I get with the generated code:
http://i.stack.imgur.com/65d1P.jpg
The curve I need:
http://i.stack.imgur.com/p3Egp.jpg
So does anyone know what goes wrong?
-edit-
And the Velocity and WhPerkm data file: http://dl.dropbox.com/u/20782274/data.mat
RE: I want to be able to retrieve the data from the residual plot
One way to do this is:
Select "Save to Workspace..." from the Fit menu
Ensure that "Save fit output to MATLAB struct named" is checked.
Note the name of variable. By default, it is output.
Click "OK" to send data to the MATLAB workspace.
In the MATLAB workspace, the residuals will be in output.residuals. For your example, you can plot the residuals via, e.g.,
>> plot( Velocity, output.residuals, '.' )