s_opticsPSF2Zcoeffs.m

PSF 2 Wernike Coefficients

Search for the Wernike polynomial coefficients that produce a target PSF.

Note this good Watson tutorial. But it has no units, wavelength, and such.

http://jov.arvojournals.org/article.aspx?articleid=2213266

BW, Vistasoft team, 2018

Contents

Create a wavefront object with some coefficients

% Create a wvf object
wave = 550;
wvf = wvfCreate('wave',wave);
wvf = wvfSet(wvf,'zcoeffs',.2,'defocus');
wvf = wvfSet(wvf,'zcoeffs',0,'vertical_astigmatism');

wvf = wvfCompute(wvf);

wvfPlot(wvf,'image psf','unit','um','plot range',15);

Get the parameters we need for the search

thisWaveUM  = wvfGet(wvf,'wave','um');
thisWaveNM  = wvfGet(wvf,'wave','nm');
pupilSizeMM = wvfGet(wvf,'pupil size','mm');
zpupilDiameterMM = wvfGet(wvf,'z pupil diameter');

pupilPlaneSizeMM = wvfGet(wvf,'pupil plane size','mm',thisWaveNM);
nPixels   = wvfGet(wvf,'spatial samples');
wvf       = wvfCompute(wvf);
psfTarget = wvfGet(wvf,'psf');

% Rewrite this function using the validated methods in wvfComputePSF.
% The current function is a version of that.  Maybe identical, but not
% validated in the same way.
f = @(x) psf2zcoeff(x,psfTarget,pupilSizeMM,zpupilDiameterMM,pupilPlaneSizeMM,thisWaveUM, nPixels);

% I should to figure out how to set the tolerances.  Default is 1e-4
zcoeffs = wvfGet(wvf,'zcoeffs');

% I am searching over the first 6 coefficients.  This includes defocus.
% Could do more, I suppose.  Also, the first coefficient ('piston') has no
% impact on the PSF.  So the search always forces that to 0.
nCoeffs = 6;
zcoeffs(1:nCoeffs)
x0 = zeros(size(zcoeffs(1:nCoeffs)));
options = optimset('PlotFcns',@optimplotfval);

x = fminsearch(f,x0,options);

% Piston comes back as an arbitrary value because the error function
% ignores it. We force it to zero here.
x(1) = 0;
ans =

         0         0         0         0    0.2000         0

Compare the values

fprintf('Estimated\n'); disp(x)
fprintf('True\n'); disp(zcoeffs(1:nCoeffs))

psf = wvfPlot(wvf,'psf','unit','um','plot range',20);

wvfEst = wvfSet(wvf,'zcoeffs',x);
wvfEst = wvfCompute(wvfEst);
psfEst = wvfPlot(wvfEst,'psf','unit','um','plot range',20);

ieNewGraphWin;
plot(psf.z(:),psfEst.z(:),'.');
identityLine;
Estimated
         0   -0.0107   -0.0018   -0.0006    0.1042    0.0004

True
         0         0         0         0    0.2000         0

Show the pupil phase functions

ieNewGraphWin([],'tall');
subplot(2,1,1), wvfPlot(wvf,'image pupil phase','unit','mm','wave',wave,'window',false)
subplot(2,1,2), wvfPlot(wvfEst,'image pupil phase','unit','mm','wave',wave,'window',false)
ans = 

  struct with fields:

    x: [-8.0657 -7.9850 -7.9044 -7.8237 -7.7430 -7.6624 … ] (1×201 double)
    y: [-8.0657 -7.9850 -7.9044 -7.8237 -7.7430 -7.6624 … ] (1×201 double)
    z: [201×201 double]


ans = 

  struct with fields:

    x: [-8.0657 -7.9850 -7.9044 -7.8237 -7.7430 -7.6624 … ] (1×201 double)
    y: [-8.0657 -7.9850 -7.9044 -7.8237 -7.7430 -7.6624 … ] (1×201 double)
    z: [201×201 double]