surface fitting using a self-defined function

I am trying to use a self-defined function to fit a surface. This self-defined function is a zernike polynomial function. It's almost working. but I got the error messege saying "Expression zernike_surf_fit(xy, a, b, c, d, e) is not a valid MATLAB expression, has non-scalar coefficients, or cannot be evaluated:"
main function is:
[X, Y] = meshgrid(linspace(-0.8, 0.8, 10), linspace(-0.8, 0.8, 10));
xy=[(X(:)-5.5)/5.5 (Y(:)-5.5)/5.5];
ft = fittype('zernike_surf_fit(xy, a, b, c, d, e)',...
'independent', {'xy'}, 'dependent', {'Z'},...
'coefficients',{'a','b','c','d','e'});
Error using fittype/testCustomModelEvaluation
Expression zernike_surf_fit(xy, a, b, c, d, e) is not a valid MATLAB expression, has non-scalar coefficients, or cannot be evaluated:
Error in fittype expression ==> zernike_surf_fit(xy, a, b, c, d, e)
??? Undefined function 'zernike_surf_fit' for input arguments of type 'double'.

Error in fittype>iCreateFittype (line 373)
testCustomModelEvaluation( obj );

Error in fittype (line 330)
obj = iCreateFittype( obj, varargin{:} );

Caused by:
Error using fittype/evaluate>I_ERROR_FCN_
Error in fittype expression ==> zernike_surf_fit(xy, a, b, c, d, e)
??? Undefined function 'zernike_surf_fit' for input arguments of type 'double'.
the zernike_surf_fit function is saved under the same file. It looks like below:
function [Z] = zernike_surf_fit(xy,a,b,c,d,e)
Z = zeros(size(xy, 1),1);
X = reshape(xy(:,1),[sqrt(length(xy(:,1))),sqrt(length(xy(:,1)))]);
Y = reshape(xy(:,2),[sqrt(length(xy(:,2))),sqrt(length(xy(:,2)))]);
%[X,Y] = meshgrid(x,y);
[theta,r] = cart2pol(X,Y);
idx = r<=1;
p = 1:5;
z = nan(size(X));
C=[a b c d e];
y = zernfun2(p,r(idx),theta(idx));
z_sum=[];
for k = 1:length(p)
z(idx) = C(k)*y(:,k);
if k==1
z_sum=z;
else
z_sum=z_sum+z;
end
end
Z_temp=reshape(z_sum,[sqrt(length(xy(:,1)))*sqrt(length(xy(:,1))),1]);
Z=Z_temp;
end
The zernike function here can generate zernike surface perfectly. So I think the only problem is the variable a b c d e.
I am really appriciate your help.

2 Comments

I suggest you try to call "zernike_surf_fit" with reasonable values for a,...,e and see what it returns for Z. MATLAB does not like the output.
Yeah if I sed the a,..,e all to a constant value. it returns a 1D array to Z, which is what I expecting. But it just cannot do any surface fitting if I use all constants. It wroks now. I just copied the code in the comment section by Matt. Thanks a lot, Torsten.

Sign in to comment.

 Accepted Answer

Your model function is not supposed to assume that the xy samples are drawn from a Cartesian grid lattice.
ft = fittype(@(a,b,c,d,e, x,y)zernike_surf_model([x,y], [a, b, c, d, e]),...
'independent', {'x','y'}, 'dependent', {'Z'},...
'coefficients',{'a','b','c','d','e'})
ft =
General model: ft(a,b,c,d,e,x,y) = zernike_surf_model([x,y],[a,b,c,d,e])
function [Z] = zernike_surf_model(xy,C)
X = xy(:,1);
Y = xy(:,2);
[theta,r] = cart2pol(X,Y);
idx = r<=1;
Z = nan(size(X));
Z(idx)=zernfun2(1:numel(C),r(idx),theta(idx)) * C(:);
end

1 Comment

Erkang
Erkang on 22 Jun 2023
Edited: Stephen23 on 22 Jun 2023
Damn Matt, that is so concise and works perfectly. Thanks you so much.

Sign in to comment.

More Answers (0)

Asked:

on 22 Jun 2023

Edited:

on 22 Jun 2023

Community Treasure Hunt

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

Start Hunting!