├── ReAlign.exe ├── 3x3.conf.sk.png ├── 5x5.conf.sk.png ├── NI_codes ├── proj │ ├── NIController.aliases │ ├── Final.vi │ ├── Global 6.vi │ ├── SetGlobal.vi │ ├── NIController.lvlps │ └── NIController.lvproj └── builds │ └── scanProj │ └── NIConrtolVersion2 │ ├── NIControl.aliases │ ├── NIControl.dll │ ├── NIControl.lib │ ├── NIControl.ini │ └── NIControl.h ├── sLFDriver.exe ├── 13x13.conf.sk.png ├── Zemax ├── Zemax_sourcefile_for_sLFM.CFG ├── Zemax_sourcefile_for_sLFM.ZDA └── Zemax_sourcefile_for_sLFM.zmx ├── PSFcalculation_calibration ├── Experimental_psf_M63_NA1.4_z1.mat ├── zeroPad.m ├── backwardProject.m ├── fresnel2D.m ├── im_shift2.m ├── calcPSFFT.m ├── SH.m ├── pixelBinning.m ├── im_shift3.m ├── calcML.m ├── intercircle.m ├── calcPSF.m ├── estimate_aberration.m ├── zernfun.m └── main_computePSF_with_calibration.m ├── Util ├── forwardProjectACC.m ├── backwardProjectACC.m ├── forwardProjectGPU.m ├── angle_order.m ├── backwardProjectGPU.m ├── Timeweighted_interp.m ├── imwriteTFSK.m └── im_shift3.m ├── SLFConfig.ini ├── Solver ├── time_weighted.m ├── deconvRL_TimeSeries.m ├── deconvRL.m └── Auto_realignment.m ├── main_for_timelapse_zebrafish_embryo.m ├── README.md └── LICENSE /ReAlign.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/ReAlign.exe -------------------------------------------------------------------------------- /3x3.conf.sk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/3x3.conf.sk.png -------------------------------------------------------------------------------- /5x5.conf.sk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/5x5.conf.sk.png -------------------------------------------------------------------------------- /NI_codes/proj/NIController.aliases: -------------------------------------------------------------------------------- 1 | [My Computer] 2 | My Computer = "192.168.38.1" 3 | 4 | -------------------------------------------------------------------------------- /sLFDriver.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/sLFDriver.exe -------------------------------------------------------------------------------- /13x13.conf.sk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/13x13.conf.sk.png -------------------------------------------------------------------------------- /NI_codes/builds/scanProj/NIConrtolVersion2/NIControl.aliases: -------------------------------------------------------------------------------- 1 | [My Computer] 2 | My Computer="localhost" -------------------------------------------------------------------------------- /NI_codes/proj/Final.vi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/NI_codes/proj/Final.vi -------------------------------------------------------------------------------- /NI_codes/proj/Global 6.vi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/NI_codes/proj/Global 6.vi -------------------------------------------------------------------------------- /NI_codes/proj/SetGlobal.vi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/NI_codes/proj/SetGlobal.vi -------------------------------------------------------------------------------- /Zemax/Zemax_sourcefile_for_sLFM.CFG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/Zemax/Zemax_sourcefile_for_sLFM.CFG -------------------------------------------------------------------------------- /Zemax/Zemax_sourcefile_for_sLFM.ZDA: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/Zemax/Zemax_sourcefile_for_sLFM.ZDA -------------------------------------------------------------------------------- /Zemax/Zemax_sourcefile_for_sLFM.zmx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/Zemax/Zemax_sourcefile_for_sLFM.zmx -------------------------------------------------------------------------------- /NI_codes/builds/scanProj/NIConrtolVersion2/NIControl.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/NI_codes/builds/scanProj/NIConrtolVersion2/NIControl.dll -------------------------------------------------------------------------------- /NI_codes/builds/scanProj/NIConrtolVersion2/NIControl.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/NI_codes/builds/scanProj/NIConrtolVersion2/NIControl.lib -------------------------------------------------------------------------------- /PSFcalculation_calibration/Experimental_psf_M63_NA1.4_z1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/THU-IBCS/DAOSLIMIT_Protocol/HEAD/PSFcalculation_calibration/Experimental_psf_M63_NA1.4_z1.mat -------------------------------------------------------------------------------- /NI_codes/builds/scanProj/NIConrtolVersion2/NIControl.ini: -------------------------------------------------------------------------------- 1 | [NIControl] 2 | server.app.propertiesEnabled=True 3 | server.ole.enabled=True 4 | server.tcp.serviceName="My Computer/VI Server" 5 | server.vi.propertiesEnabled=True 6 | WebServer.TcpAccess="c+*" 7 | WebServer.ViAccess="+*" 8 | DebugServerEnabled=False 9 | DebugServerWaitOnLaunch=False 10 | 11 | -------------------------------------------------------------------------------- /PSFcalculation_calibration/zeroPad.m: -------------------------------------------------------------------------------- 1 | function xout = zeroPad(xin, zeroImage) 2 | %% Robert's code 3 | %% Reference: Robert Prevede, Young-Gyu Yoon, Maximilian Hoffmann, Nikita Pak.etc. 4 | %% "Simultaneous whole-animal 3D imaging of neuronal activity using light-field microscopy " 5 | %% in Nature Methods VOL.11 NO.7|July 2014. 6 | xout = zeroImage; 7 | xout( 1:size(xin,1), 1:size(xin,2) ) = xin; -------------------------------------------------------------------------------- /NI_codes/proj/NIController.lvlps: -------------------------------------------------------------------------------- 1 | [ProjectWindow_Data] 2 | ProjectExplorer.ClassicPosition[String] = "288,380,617,1425" 3 | 4 | [AB_Cache_{5290F2B0-B175-45AE-9523-505CDD81EDE4}] 5 | Cache_Path[Path] Line0001 = "/C/Users/NYX/AppData/Local/Temp/AB_Cache_{5290F2B0" 6 | Cache_Path[Path] Line0002 = "-B175-45AE-9523-505CDD81EDE4}.txt" 7 | 8 | [AB_Cache_{495918CE-82C4-4699-90FA-DABCCED1C399}] 9 | Cache_Path[Path] Line0001 = "/C/Users/NYX/AppData/Local/Temp/AB_Cache_{495918CE" 10 | Cache_Path[Path] Line0002 = "-82C4-4699-90FA-DABCCED1C399}.txt" 11 | 12 | -------------------------------------------------------------------------------- /Util/forwardProjectACC.m: -------------------------------------------------------------------------------- 1 | function projection = forwardProjectACC(psf,Xguess) 2 | %% Forward projection from 3D volume to 2D projetion (using CPU) 3 | %% Input: 4 | % @psf: the phase space PSF 5 | % @Xguess: the projection obtained from "forward project" 6 | %% Output: 7 | % projection: estimate volume 8 | % 9 | % [1] JIAMIN WU, ZHI LU and DONG JIANG etc, 10 | % Iterative tomography with digital adaptive optics permits hour-long intravital observation of 3D subcellular dynamics at millisecond scale 11 | % Cell, 2021. 12 | % 13 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 14 | % Date : 10/24/2020 15 | 16 | projection=zeros(size(Xguess,1),size(Xguess,2)); 17 | for z=1:size(Xguess,3) 18 | projection=projection+conv2(Xguess(:,:,z),psf(:,:,z),'same'); 19 | end 20 | 21 | end 22 | 23 | -------------------------------------------------------------------------------- /Util/backwardProjectACC.m: -------------------------------------------------------------------------------- 1 | function Backprojection = backwardProjectACC(psf,projection) 2 | %% Backprojection from 2D projetion to 3D volume (using CPU) 3 | %% Input: 4 | % @psf: the phase space PSF 5 | % @projection: the projection obtained from "forward project". 6 | %% Output: 7 | % Backprojection: estimate volume 8 | % 9 | % [1] JIAMIN WU, ZHI LU and DONG JIANG etc, 10 | % Iterative tomography with digital adaptive optics permits hour-long intravital observation of 3D subcellular dynamics at millisecond scale 11 | % Cell, 2021. 12 | % 13 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 14 | % Date : 10/24/2020 15 | psf=rot90(psf,2); 16 | Backprojection=zeros(size(projection,1),size(projection,2),size(psf,3)); 17 | for z=1:size(psf,3) 18 | Backprojection(:,:,z)=conv2(projection,psf(:,:,z),'same'); 19 | end 20 | 21 | -------------------------------------------------------------------------------- /PSFcalculation_calibration/backwardProject.m: -------------------------------------------------------------------------------- 1 | function Backprojection = backwardProject(H, projection, Nnum ) 2 | %% Robert's code 3 | %% Reference: Robert Prevede, Young-Gyu Yoon, Maximilian Hoffmann, Nikita Pak.etc. 4 | %% "Simultaneous whole-animal 3D imaging of neuronal activity using light-field microscopy " 5 | %% in Nature Methods VOL.11 NO.7|July 2014. 6 | 7 | x3length = size(H,5); 8 | Backprojection = zeros(size(projection, 1), size(projection, 1), x3length ); 9 | for aa=1:Nnum, 10 | for bb=1:Nnum, 11 | for cc=1:x3length, 12 | 13 | Ht = imrotate( H(:,:,aa,bb,cc), 180); 14 | tempSlice = conv2(projection, Ht, 'same'); 15 | Backprojection((aa:Nnum:end) , (bb:Nnum:end),cc) = Backprojection((aa:Nnum:end) , (bb:Nnum:end),cc) + tempSlice( (aa:Nnum:end) , (bb:Nnum:end) ); 16 | end 17 | end 18 | end 19 | 20 | -------------------------------------------------------------------------------- /NI_codes/builds/scanProj/NIConrtolVersion2/NIControl.h: -------------------------------------------------------------------------------- 1 | #include "extcode.h" 2 | #ifdef __cplusplus 3 | extern "C" { 4 | #endif 5 | 6 | /*! 7 | * Kx_4_ZScanning 8 | */ 9 | void __cdecl Kx_4_ZScanning(LVBoolean start, int32_t laser1, int32_t laser2, 10 | int32_t laser3, int32_t laser4, int32_t k, double IfScanning, 11 | double DCOffsetX, double DCOffsetY, double XShiftRatio, double YShiftRatio, 12 | double VXPX, double VYPY, LStrHandle *VoltageScanningChannel, 13 | LStrHandle *LaserTriggerChannel, double frequency, double z_num, 14 | double delta_zX1um, int32_t Mode, double LoopDelaySecond, 15 | double TriggerDelayMs, double RotationAlpha, double RotationBeta, 16 | double ExposureTimeMs, double User1_float, int32_t User2_int); 17 | /*! 18 | * SetStop 19 | */ 20 | void __cdecl SetStop(int32_t stop); 21 | 22 | MgErr __cdecl LVDLLStatus(char *errStr, int errStrLen, void *module); 23 | 24 | void __cdecl SetExecuteVIsInPrivateExecutionSystem(Bool32 value); 25 | 26 | #ifdef __cplusplus 27 | } // extern "C" 28 | #endif 29 | 30 | -------------------------------------------------------------------------------- /Util/forwardProjectGPU.m: -------------------------------------------------------------------------------- 1 | function projection = forwardProjectGPU(psf,Xguess) 2 | %% Forward projection from 3D volume to 2D projetion (using CPU) 3 | %% Input: 4 | % @psf: the phase space PSF 5 | % @Xguess: the projection obtained from "forward project" 6 | %% Output: 7 | % projection: estimate volume 8 | % 9 | % [1] JIAMIN WU, ZHI LU and DONG JIANG etc, 10 | % Iterative tomography with digital adaptive optics permits hour-long intravital observation of 3D subcellular dynamics at millisecond scale 11 | % Cell, 2021. 12 | % 13 | % Author: ZHI LU (luz18@mails.tsinghua.edu.cn) 14 | % Date : 10/24/2020 15 | 16 | projection=gpuArray.zeros(size(Xguess,1),size(Xguess,2),'single'); 17 | 18 | [ra ca]=size(Xguess(:,:,1)); 19 | [rb cb]=size(psf(:,:,1)); 20 | r = ra+rb-1;c=ca+cb-1; p1 = (r-ra)/2; 21 | a1 = gpuArray.zeros(r,r,'single'); 22 | b1 = gpuArray.zeros(r,r,'single'); 23 | for z=1:size(Xguess,3) 24 | %% 25 | a1(1:ra,1:ca) = Xguess(:,:,z) ; 26 | b1(1:rb,1:cb) = psf(:,:,z) ; 27 | clear con1; 28 | con1 = ifft2(fft2(a1).*fft2(b1)); 29 | projection = projection + real(con1(p1+1:r-p1,p1+1:r-p1)); 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /Util/angle_order.m: -------------------------------------------------------------------------------- 1 | function [index1,index2] = angle_order(Nnum) 2 | % Auto angle order generation for tomographic reconstrcution 3 | % 4 | % The Code is created based on the method described in the following paper 5 | % [1] ZHI LU etc, 6 | % "A practical guide to scanning light-field microscopy with digital adaptive optics" 7 | % Nature Protocols, 2022 8 | % 9 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 10 | % Date : 10/01/2021 11 | 12 | [xx,yy]=meshgrid(1:Nnum+2, 1:Nnum+2); 13 | index1=[]; 14 | index2=[]; 15 | for i=1:round((1+Nnum)/2) 16 | endXY=Nnum+1-i; 17 | for j=i:endXY 18 | index1=[index1,yy(i,j)]; 19 | index2=[index2,xx(i,j)]; 20 | end 21 | for j=i+1:endXY 22 | index1=[index1,yy(j,endXY)]; 23 | index2=[index2,xx(j,endXY)]; 24 | end 25 | if ieqtol | abs(mod(SHIFTY,1))>eqtol 13 | error('SHIFTX and SHIFTY should be integer numbers'); 14 | end 15 | 16 | % if SHIFTX >= xlength | SHIFTY >= ylength, 17 | % error('SHIFTX and SHIFTY should be smaller than size(img,1) and size(img,2), respectively'); 18 | % end 19 | 20 | 21 | 22 | SHIFTX = round(SHIFTX); 23 | SHIFTY = round(SHIFTY); 24 | 25 | new_im = zeros(xlength, ylength, size(img,3) ); 26 | 27 | if SHIFTX >=0 & SHIFTY >= 0, 28 | new_im( (1+SHIFTX:end), (1+SHIFTY:end),:) = img( (1:end-SHIFTX), (1:end-SHIFTY),:); 29 | elseif SHIFTX >=0 & SHIFTY < 0, 30 | new_im( (1+SHIFTX:end), (1:end+SHIFTY),:) = img( (1:end-SHIFTX), (-SHIFTY+1:end),:); 31 | elseif SHIFTX <0 & SHIFTY >= 0, 32 | new_im( (1:end+SHIFTX), (1+SHIFTY:end),:) = img( (-SHIFTX+1:end), (1:end-SHIFTY),:); 33 | else 34 | new_im( (1:end+SHIFTX), (1:end+SHIFTY),:) = img( (-SHIFTX+1:end), (-SHIFTY+1:end),:); 35 | end 36 | 37 | 38 | end -------------------------------------------------------------------------------- /SLFConfig.ini: -------------------------------------------------------------------------------- 1 | [APPCON] 2 | AppMode = LZ 3 | 4 | [CAMERA] 5 | TriggerMode = 1 6 | CaptureMode = 0 7 | Exposure = 5.000000 8 | ImageNum = 10 9 | BitMin = 3011 10 | BitMax = 5629 11 | Nshift = 3 12 | Nx = 153 13 | Ny = 153 14 | Nnum = 13 15 | StartX = 0 16 | StartY = 0 17 | ViewPosX = 6 18 | ViewPosY = 6 19 | preResize = 1.000000 20 | slightRotate = 0.000000 21 | WarpFile = 22 | 23 | [NICARD] 24 | laser1 = 0 25 | laser2 = 0 26 | laser3 = 0 27 | laser4 = 0 28 | k = 3 29 | IfScan = 1.000000 30 | dcX = 5.000000 31 | dcY = 5.000000 32 | freq = 9.000000 33 | scanChan = Dev1/ao0:3 34 | laserChan = Dev1/port0 35 | TriggerDelay = 1.000000 36 | LoopDelay = 0.000000 37 | Exposure = 99.000000 38 | ShiftX = 0.012580 39 | ShiftY = -0.010000 40 | PixelVoltageX = 0.104480 41 | PixelVoltageY = 0.088050 42 | 43 | [CHANNEL] 44 | cLaser0 = false 45 | cLaser0Min = 0 46 | cLaser0Max = 65535 47 | cLaser0Color0 = false 48 | cLaser0Color1 = false 49 | cLaser0Color2 = false 50 | cLaser1 = true 51 | cLaser1Min = 3077 52 | cLaser1Max = 5521 53 | cLaser1Color0 = false 54 | cLaser1Color1 = true 55 | cLaser1Color2 = true 56 | cLaser2 = false 57 | cLaser2Min = 0 58 | cLaser2Max = 65535 59 | cLaser2Color0 = false 60 | cLaser2Color1 = false 61 | cLaser2Color2 = false 62 | cLaser3 = false 63 | cLaser3Min = 0 64 | cLaser3Max = 65535 65 | cLaser3Color0 = false 66 | cLaser3Color1 = false 67 | cLaser3Color2 = false 68 | -------------------------------------------------------------------------------- /PSFcalculation_calibration/calcPSFFT.m: -------------------------------------------------------------------------------- 1 | function [psfLine] = calcPSFFT(p3, fobj, NA, x1space, scale, lambda, fml, M, n) 2 | %% Robert's code 3 | %% Reference: Robert Prevede, Young-Gyu Yoon, Maximilian Hoffmann, Nikita Pak.etc. 4 | %% "Simultaneous whole-animal 3D imaging of neuronal activity using light-field microscopy " 5 | %% in Nature Methods VOL.11 NO.7|July 2014. 6 | 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | k = 2*pi*n/lambda; 9 | alpha = asin(NA/n); 10 | p1 = 0; 11 | p2 = 0; 12 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 13 | 14 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 15 | psfLine = zeros(1,length(x1space)); 16 | parfor a=1:length(x1space), 17 | x1 = x1space(a); 18 | x2 = 0; 19 | xL2normsq = (((x1+M*p1)^2+(x2+M*p2)^2)^0.5)/M; 20 | v = k*xL2normsq*sin(alpha); 21 | u = 4*k*p3*(sin(alpha/2)^2); 22 | 23 | Koi = M/((fobj*lambda)^2)*exp(-i*u/(4*(sin(alpha/2)^2))); 24 | intgrand = @(theta) (sqrt(cos(theta))) .* (1+cos(theta)) .* (exp(-(i*u/2)* (sin(theta/2).^2) / (sin(alpha/2)^2))) .* (besselj(0, sin(theta)/sin(alpha)*v)) .* (sin(theta)); 25 | I0 = integral(@(theta)intgrand (theta),0,alpha); 26 | 27 | psfLine(a) = Koi*I0; 28 | end 29 | psfLine = abs(psfLine.^2)/max(abs(psfLine.^2)); 30 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 31 | -------------------------------------------------------------------------------- /PSFcalculation_calibration/SH.m: -------------------------------------------------------------------------------- 1 | function z = SH(c,data) % Zernike polynomial generation 2 | %% Input: 3 | % @c: Zernike index 4 | % @data: 2D meshgrid 5 | %% Ouput: 6 | % z: zernike polynomial 7 | % 8 | % [1] ZHI LU etc, 9 | % "A practical guide to scanning light-field microscopy with digital adaptive optics" 10 | % Nature Protocols, 2022 11 | 12 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 13 | % Date : 07/24/2021 14 | 15 | x=data(1,:); 16 | y=data(2,:); 17 | [X,Y]=meshgrid(x,y); 18 | [theta,r]=cart2pol(X,Y); % polar coordinates 19 | idx=r<=1; 20 | zz=zeros(size(X)); 21 | 22 | b = c(1:4); 23 | a = c(5:end); 24 | 25 | zz(idx)=b(1)*zernfun(0,0,r(idx),theta(idx))+b(2)*zernfun(1,1,r(idx),theta(idx))+b(3)*zernfun(1,-1,r(idx),theta(idx))+b(4)*zernfun(2,0,r(idx),theta(idx))+... 26 | a(1)*zernfun(2,2,r(idx),theta(idx))+a(2)*zernfun(2,-2,r(idx),theta(idx))+a(3)*zernfun(3,1,r(idx),theta(idx))+... 27 | a(4)*zernfun(3,-1,r(idx),theta(idx))+a(5)*zernfun(3,3,r(idx),theta(idx))+a(6)*zernfun(3,-3,r(idx),theta(idx))+... 28 | a(7)*zernfun(4,0,r(idx),theta(idx))+a(8)*zernfun(4,2,r(idx),theta(idx))+a(9)*zernfun(4,-2,r(idx),theta(idx))+... 29 | a(10)*zernfun(4,4,r(idx),theta(idx))+a(11)*zernfun(4,-4,r(idx),theta(idx))+a(12)*zernfun(5,1,r(idx),theta(idx))+... 30 | a(13)*zernfun(5,-1,r(idx),theta(idx))+a(14)*zernfun(5,3,r(idx),theta(idx))+a(15)*zernfun(5,-3,r(idx),theta(idx))+... 31 | a(16)*zernfun(5,5,r(idx),theta(idx))+a(17)*zernfun(5,-5,r(idx),theta(idx)); 32 | 33 | 34 | z=zz; 35 | -------------------------------------------------------------------------------- /PSFcalculation_calibration/pixelBinning.m: -------------------------------------------------------------------------------- 1 | function [OIMG, x1shift, x2shift] = pixelBinning(SIMG, OSR) 2 | %% Robert's code 3 | %% Reference: Robert Prevede, Young-Gyu Yoon, Maximilian Hoffmann, Nikita Pak.etc. 4 | %% "Simultaneous whole-animal 3D imaging of neuronal activity using light-field microscopy " 5 | %% in Nature Methods VOL.11 NO.7|July 2014. 6 | 7 | x1length = size(SIMG,1); 8 | x2length = size(SIMG,2); 9 | 10 | x1center = (x1length-1)/2 + 1; 11 | x2center = (x2length-1)/2 + 1; 12 | 13 | x1centerinit = x1center - (OSR-1)/2; 14 | x2centerinit = x2center - (OSR-1)/2; 15 | x1init = x1centerinit - floor(x1centerinit/OSR)*OSR ; 16 | x2init = x2centerinit - floor(x2centerinit/OSR)*OSR ; 17 | 18 | 19 | x1shift = 0; 20 | x2shift = 0; 21 | if x1init<1, 22 | x1init = x1init + OSR; 23 | x1shift = 1; 24 | end 25 | if x2init<1, 26 | x2init = x2init + OSR; 27 | x2shift = 1; 28 | end 29 | 30 | 31 | % SIMG_crop = SIMG( (x1init:1:end-OSR+1), (x2init:1:end-OSR+1) ); 32 | % SIMG_crop = SIMG_crop( (1:1: floor(size(SIMG_crop,1)/OSR)*OSR) , (1:1: floor(size(SIMG_crop,2)/OSR)*OSR) ); 33 | halfWidth = length( (x1init:x1center-1) ); 34 | SIMG_crop = SIMG( [ (x1init:x1center-1) x1center x1center+1:x1center+halfWidth ], [ (x2init:x2center-1) x2center x2center+1:x2center+halfWidth ] ); 35 | 36 | 37 | %%%%%%%%%%%%%%%%%% PIXEL BINNING %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 38 | [m,n]=size(SIMG_crop); %M is the original matrix 39 | SIMG_crop = sum( reshape(SIMG_crop,OSR,[]) ,1 ); 40 | SIMG_crop=reshape(SIMG_crop,m/OSR,[]).'; %Note transpose 41 | SIMG_crop=sum( reshape(SIMG_crop,OSR,[]) ,1); 42 | OIMG =reshape(SIMG_crop,n/OSR,[]).'; %Note transpose 43 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /Util/imwriteTFSK.m: -------------------------------------------------------------------------------- 1 | function [] = imwriteTFSK(Volume,name) 2 | %% write 3D image file 3 | %% supported formats: single/double/uint8/uint16 4 | %% Input: 5 | % @Volume: the 3D image 6 | % @name: the file path 7 | % 8 | % [1] JIAMIN WU, ZHI LU and DONG JIANG etc, 9 | % Iterative tomography with digital adaptive optics permits hour-long intravital observation of 3D subcellular dynamics at millisecond scale 10 | % Cell, 2021. 11 | % 12 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 13 | % Date : 10/24/2020 14 | 15 | t = Tiff(name,'w'); % Filename by variable name 16 | tagstruct.ImageLength = size(Volume,1); 17 | tagstruct.ImageWidth = size(Volume,2); 18 | tagstruct.Photometric = Tiff.Photometric.MinIsBlack; 19 | if(class(Volume) == 'single') 20 | tagstruct.BitsPerSample = 32; 21 | tagstruct.SampleFormat = Tiff.SampleFormat.IEEEFP; 22 | elseif(class(Volume) == 'double') 23 | warning('ImageJ may not support double/64-bit tiff!'); 24 | tagstruct.BitsPerSample = 64; 25 | tagstruct.SampleFormat = Tiff.SampleFormat.IEEEFP; 26 | elseif(class(Volume) == 'uint8') 27 | tagstruct.BitsPerSample = 8; 28 | tagstruct.SampleFormat = Tiff.SampleFormat.UInt; 29 | elseif(class(Volume) == 'uint16') 30 | tagstruct.BitsPerSample = 16; 31 | tagstruct.SampleFormat = Tiff.SampleFormat.UInt; 32 | end 33 | tagstruct.SamplesPerPixel = 1; 34 | tagstruct.RowsPerStrip = 16; 35 | tagstruct.PlanarConfiguration = Tiff.PlanarConfiguration.Chunky; 36 | tagstruct.Software = 'MATLAB'; 37 | setTag(t,tagstruct) 38 | write(t,squeeze(Volume(:,:,1))); 39 | for i=2:size(Volume,3) % Write image data to the file 40 | writeDirectory(t); 41 | setTag(t,tagstruct) 42 | write(t,squeeze(Volume(:,:,i))); % Append 43 | end 44 | close(t); 45 | end 46 | 47 | -------------------------------------------------------------------------------- /Util/im_shift3.m: -------------------------------------------------------------------------------- 1 | function new_im = im_shift3(img, SHIFTX, SHIFTY) 2 | %% Input: 3 | % @img: the 3D image 4 | % @SHIFTX: the shift in the first dimension 5 | % @SHIFTY: the shift in the second dimension 6 | %% Output: 7 | % new_im: the shifted 3D image 8 | % 9 | % [1] JIAMIN WU, ZHI LU and DONG JIANG etc, 10 | % Iterative tomography with digital adaptive optics permits hour-long intravital observation of 3D subcellular dynamics at millisecond scale 11 | % Cell, 2021. 12 | % 13 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 14 | % Date : 10/24/2020 15 | % 16 | %% modified from Robert's code (im_shift2.m) 17 | %% Reference: Robert Prevede, Young-Gyu Yoon, Maximilian Hoffmann, Nikita Pak.etc. 18 | %% "Simultaneous whole-animal 3D imaging of neuronal activity using light-field microscopy " 19 | %% in Nature Methods VOL.11 NO.7|July 2014. 20 | 21 | eqtol = 1e-10; 22 | 23 | xlength = size(img,1); 24 | ylength = size(img,2); 25 | 26 | if abs(mod(SHIFTX,1))>eqtol | abs(mod(SHIFTY,1))>eqtol 27 | error('SHIFTX and SHIFTY should be integer numbers'); 28 | end 29 | 30 | % if SHIFTX >= xlength | SHIFTY >= ylength, 31 | % error('SHIFTX and SHIFTY should be smaller than size(img,1) and size(img,2), respectively'); 32 | % end 33 | 34 | 35 | 36 | SHIFTX = round(SHIFTX); 37 | SHIFTY = round(SHIFTY); 38 | 39 | new_im = zeros(xlength, ylength,size(img,3)); 40 | 41 | if SHIFTX >=0 & SHIFTY >= 0, 42 | new_im( (1+SHIFTX:end), (1+SHIFTY:end) ,:) = img( (1:end-SHIFTX), (1:end-SHIFTY) ,:); 43 | elseif SHIFTX >=0 & SHIFTY < 0, 44 | new_im( (1+SHIFTX:end), (1:end+SHIFTY) ,:) = img( (1:end-SHIFTX), (-SHIFTY+1:end) ,:); 45 | elseif SHIFTX <0 & SHIFTY >= 0, 46 | new_im( (1:end+SHIFTX), (1+SHIFTY:end) ,:) = img( (-SHIFTX+1:end), (1:end-SHIFTY) ,:); 47 | else 48 | new_im( (1:end+SHIFTX), (1:end+SHIFTY) ,:) = img( (-SHIFTX+1:end), (-SHIFTY+1:end) ,:); 49 | end 50 | 51 | 52 | end 53 | -------------------------------------------------------------------------------- /PSFcalculation_calibration/im_shift3.m: -------------------------------------------------------------------------------- 1 | function new_im = im_shift3(img, SHIFTX, SHIFTY) 2 | %% Input: 3 | % @img: the 3D image 4 | % @SHIFTX: the shift in the first dimension 5 | % @SHIFTY: the shift in the second dimension 6 | %% Output: 7 | % new_im: the shifted 3D image 8 | % 9 | % [1] JIAMIN WU, ZHI LU and DONG JIANG.etc, 10 | % "Iterative tomography with digital adaptive optics permits hour-long intravital observation of 3D subcellular dynamics at millisecond scale" 11 | % Cell, 2021. 12 | % 13 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 14 | % Date : 10/24/2020 15 | % 16 | %% modified from Robert's code (im_shift2.m) 17 | %% Reference: Robert Prevede, Young-Gyu Yoon, Maximilian Hoffmann, Nikita Pak.etc. 18 | %% "Simultaneous whole-animal 3D imaging of neuronal activity using light-field microscopy " 19 | %% in Nature Methods VOL.11 NO.7|July 2014. 20 | 21 | eqtol = 1e-10; 22 | 23 | xlength = size(img,1); 24 | ylength = size(img,2); 25 | 26 | if abs(mod(SHIFTX,1))>eqtol | abs(mod(SHIFTY,1))>eqtol 27 | error('SHIFTX and SHIFTY should be integer numbers'); 28 | end 29 | 30 | % if SHIFTX >= xlength | SHIFTY >= ylength, 31 | % error('SHIFTX and SHIFTY should be smaller than size(img,1) and size(img,2), respectively'); 32 | % end 33 | 34 | 35 | 36 | SHIFTX = round(SHIFTX); 37 | SHIFTY = round(SHIFTY); 38 | 39 | new_im = zeros(xlength, ylength,size(img,3)); 40 | 41 | if SHIFTX >=0 & SHIFTY >= 0, 42 | new_im( (1+SHIFTX:end), (1+SHIFTY:end) ,:) = img( (1:end-SHIFTX), (1:end-SHIFTY) ,:); 43 | elseif SHIFTX >=0 & SHIFTY < 0, 44 | new_im( (1+SHIFTX:end), (1:end+SHIFTY) ,:) = img( (1:end-SHIFTX), (-SHIFTY+1:end) ,:); 45 | elseif SHIFTX <0 & SHIFTY >= 0, 46 | new_im( (1:end+SHIFTX), (1+SHIFTY:end) ,:) = img( (-SHIFTX+1:end), (1:end-SHIFTY) ,:); 47 | else 48 | new_im( (1:end+SHIFTX), (1:end+SHIFTY) ,:) = img( (-SHIFTX+1:end), (-SHIFTY+1:end) ,:); 49 | end 50 | 51 | 52 | end -------------------------------------------------------------------------------- /Solver/time_weighted.m: -------------------------------------------------------------------------------- 1 | function WDF=time_weighted(WDF,time_weight_index,index1,index2,Nshift,Nnum,frame) 2 | 3 | % Timeweighted algorithm: adjust the weight in different 4 | % ...scanning sampling points to remove motion artefacts 5 | % The Code is created based on the method described in the following paper 6 | % [1] JIAMIN WU, ZHI LU and DONG JIANG etc, 7 | % Iterative tomography with digital adaptive optics permits hour-long intravital observation of 3D subcellular dynamics at millisecond scale 8 | % Cell, 2021. 9 | % 10 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 11 | % Date : 10/24/2020 12 | 13 | addpath('./Util/'); 14 | 15 | 16 | % Data processing 17 | WDF=WDF+1e-5; 18 | index=zeros( size(WDF) ); 19 | now1=mod(frame,Nshift*Nshift); %% the scanning position at the moment 20 | now_index1=[index1(now1+1:end),index1(1:now1)]; %% the scanning order at the moment 21 | now_index2=[index2(now1+1:end),index2(1:now1)]; %% the scanning order at the moment 22 | 23 | % Weight distribution according to time and scanning positions 24 | for time_aver=1:1:Nshift*Nshift+1 25 | if time_aver == Nshift*Nshift+1 26 | time_mask_wigner=ones(size(WDF,1),size(WDF,2),size(WDF,3),size(WDF,4)); 27 | else 28 | time_mask_wigner=zeros(size(WDF,1),size(WDF,2),size(WDF,3),size(WDF,4)); 29 | time_mask_wigner(Nshift+1-now_index2(time_aver):Nshift:end,Nshift+1-now_index1(time_aver):Nshift:end,:,: )=1; 30 | end 31 | WDF_t=WDF.*time_mask_wigner; 32 | if time_aver ~= Nshift*Nshift+1 33 | index(WDF_t ~= 0) =time_weight_index^(abs(time_aver-round(Nshift^2/2))); 34 | end 35 | end 36 | 37 | % TimeWeighted 38 | WDF_TW =zeros(size(WDF,1),size(WDF,2),Nnum,Nnum); 39 | for i = 1:Nnum 40 | for j = 1:Nnum 41 | datanew = Timeweighted_interp(WDF_t(:,:,i,j),index(:,:,i,j),index2,index1,Nshift); 42 | datanew(isnan(datanew))=0; 43 | WDF_TW(:,:,i,j)=gather(datanew); 44 | end 45 | end 46 | WDF_TW(WDF_TW<0)=0; 47 | WDF=WDF_TW(Nshift+1:end-Nshift,Nshift+1:end-Nshift,:,:); 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /PSFcalculation_calibration/calcML.m: -------------------------------------------------------------------------------- 1 | function MLARRAY = calcML(fml, k, x1MLspace, x2MLspace, x1space, x2space) 2 | %% Robert's code 3 | %% Reference: Robert Prevede, Young-Gyu Yoon, Maximilian Hoffmann, Nikita Pak.etc. 4 | %% "Simultaneous whole-animal 3D imaging of neuronal activity using light-field microscopy " 5 | %% in Nature Methods VOL.11 NO.7|July 2014. 6 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 7 | x1length = length(x1space); 8 | x2length = length(x2space); 9 | x1MLdist = length(x1MLspace); 10 | x2MLdist = length(x2MLspace); 11 | x1center = find(x1space==0); 12 | x2center = find(x2space==0); 13 | x1centerALL = [ (x1center: -x1MLdist:1) (x1center + x1MLdist: x1MLdist :x1length)]; 14 | x1centerALL = sort(x1centerALL); 15 | x2centerALL = [ (x2center: -x2MLdist:1) (x2center + x2MLdist: x2MLdist :x2length)]; 16 | x2centerALL = sort(x2centerALL); 17 | 18 | zeroline = zeros(1, length(x2space) ); 19 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 20 | 21 | 22 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 23 | patternML = zeros( length(x1MLspace), length(x2MLspace) ); 24 | patternMLcp = zeros( length(x1MLspace), length(x2MLspace) ); 25 | for a=1:length(x1MLspace), 26 | for b=1:length(x2MLspace), 27 | x1 = x1MLspace(a); 28 | x2 = x2MLspace(b); 29 | xL2norm = x1^2 + x2^2; 30 | 31 | 32 | patternML(a,b) = exp(-i*k/(2*fml)*xL2norm); 33 | patternMLcp(a,b) = exp(-0.05*i*k/(2*fml)*xL2norm); 34 | end 35 | end 36 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 37 | 38 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 39 | MLspace = zeros( length(x1space), length(x2space) ); 40 | MLcenters = MLspace; 41 | for a=1:length(x1centerALL), 42 | for b=1:length(x2centerALL), 43 | MLcenters( x1centerALL(a), x2centerALL(b)) = 1; 44 | end 45 | end 46 | MLARRAY = conv2(MLcenters, patternML, 'same'); 47 | MLARRAYcp = conv2(MLcenters, patternMLcp, 'same'); 48 | 49 | MLARRAYcpANG = angle(MLARRAYcp); 50 | MLARRAYcpANG = MLARRAYcpANG - min(min(MLARRAYcpANG)) + 0.0; 51 | MLARRAYcpANGnorm = MLARRAYcpANG/max(max(MLARRAYcpANG)); 52 | 53 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /PSFcalculation_calibration/intercircle.m: -------------------------------------------------------------------------------- 1 | function calcu_phase = intercircle(calcu_dephase,maxIte) % 2D discrete intergration using the iterative method 2 | %% Input: 3 | % @calcu_dephase: the 2D differential of the phase 4 | % @maxIte: the maximum iteration times 5 | %% Ouput: 6 | % calcu_phase: 2D phase calculated by intergration 7 | % 8 | % [1] ZHI LU etc, 9 | % "A practical guide to scanning light-field microscopy with digital adaptive optics" 10 | % Nature Protocols, 2022 11 | 12 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 13 | % Date : 07/24/2021 14 | 15 | [rr,cc,~] = size(calcu_dephase); 16 | ddx = 1/rr; 17 | ddy = 1/cc; 18 | dfx=squeeze(calcu_dephase(:,:,1)); 19 | dfy=squeeze(calcu_dephase(:,:,2)); 20 | ra = (rr-1)/2; 21 | [X,Y]=meshgrid([-ra:ra],[-ra:ra]); 22 | dfx( (X.^2+Y.^2)>(ra)^2 )=0; 23 | dfy( (X.^2+Y.^2)>(ra)^2 )=0; 24 | mask = X.^2+Y.^2<=(ra^2); % maxmium frequency range 25 | 26 | calcu_phase=zeros(size(calcu_dephase,1),size(calcu_dephase,2)); 27 | centerX = (rr+1)/2; 28 | centerY = (rr+1)/2; 29 | 30 | Nnum=rr; 31 | for u=1:Nnum 32 | for v=1:Nnum % for different spatial angular components, respectively 33 | if(mask(u,v)==0) 34 | continue; 35 | end 36 | record = 0; 37 | count = 0; 38 | 39 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 40 | %%%%%%%%%%%%%%%%%%%%%%% 2D Integration %%%%%%%%%%%%%%%%%%%%%%%%%%% 41 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 42 | for i = 1:maxIte 43 | step = zeros(1,u+v-2); 44 | sr = v-1; 45 | sd = u-1; 46 | cs=randperm(length(step)); 47 | step(cs(1:sr)) = 1; 48 | r2 = 0; 49 | rr = 1; 50 | cc = 1; 51 | for ids = 1:length(step) 52 | if(step(ids)==1) 53 | r2 = r2+dfy(rr,cc)*ddy; 54 | cc = cc+1; 55 | else 56 | r2 = r2+dfx(rr,cc)*ddx; 57 | rr = rr+1; 58 | end 59 | 60 | end 61 | record = record+r2; 62 | end 63 | calcu_phase(u,v) = record/(maxIte); 64 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 65 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 66 | 67 | 68 | 69 | 70 | end 71 | end 72 | calcu_phase( (X.^2+Y.^2)>ra^2 )=0; 73 | end 74 | 75 | -------------------------------------------------------------------------------- /PSFcalculation_calibration/calcPSF.m: -------------------------------------------------------------------------------- 1 | function [psf, LFpsf] = calcPSF(p1, p2, p3, fobj, NA, x1space, x2space, scale, lambda, MLARRAY, fml, M, n, centerArea) 2 | %% Robert's code 3 | %% Reference: Robert Prevede, Young-Gyu Yoon, Maximilian Hoffmann, Nikita Pak.etc. 4 | %% "Simultaneous whole-animal 3D imaging of neuronal activity using light-field microscopy " 5 | %% in Nature Methods VOL.11 NO.7|July 2014. 6 | 7 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 8 | k = 2*pi*n/lambda; 9 | alpha = asin(NA/n); 10 | x1length = length(x1space); 11 | x2length = length(x2space); 12 | zeroline = zeros(1, length(x2space) ); 13 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 14 | 15 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 16 | pattern = zeros(x1length, x2length); 17 | centerPT = ceil(length(x1space)/2); 18 | parfor a=centerArea(1):centerPT, 19 | patternLine = zeroline; 20 | for b=a:centerPT, 21 | x1 = x1space(a); 22 | x2 = x2space(b); 23 | xL2normsq = (((x1+M*p1)^2+(x2+M*p2)^2)^0.5)/M; 24 | 25 | v = k*xL2normsq*sin(alpha); 26 | u = 4*k*(p3*1)*(sin(alpha/2)^2); 27 | Koi = M/((fobj*lambda)^2)*exp(-i*u/(4*(sin(alpha/2)^2))); 28 | intgrand = @(theta) (sqrt(cos(theta))) .* (1+cos(theta)) .* (exp(-(i*u/2)* (sin(theta/2).^2) / (sin(alpha/2)^2))) .* (besselj(0, sin(theta)/sin(alpha)*v)) .* (sin(theta)); 29 | I0 = integral(@(theta)intgrand (theta),0,alpha); 30 | 31 | patternLine(1,b) = Koi*I0; 32 | end 33 | pattern(a,:) = patternLine; 34 | end 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | 37 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 38 | patternA = pattern( (1:centerPT), (1:centerPT) ); 39 | patternAt = fliplr(patternA); 40 | 41 | pattern3D = zeros(size(pattern,1), size(pattern,2), 4); 42 | pattern3D(:,:,1) = pattern; 43 | pattern3D( (1:centerPT), (centerPT:end),1 ) = patternAt; 44 | pattern3D(:,:,2) = rot90( pattern3D(:,:,1) , -1); 45 | pattern3D(:,:,3) = rot90( pattern3D(:,:,1) , -2); 46 | pattern3D(:,:,4) = rot90( pattern3D(:,:,1) , -3); 47 | 48 | pattern = max(pattern3D,[],3); 49 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 50 | 51 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 52 | %%%%%%%%%%%%%%%%%%% CALCAULTED LF PSF %%%%%%%%%%%%%%%%%%%%%%%%%%% 53 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54 | [f1,dx1,x1]=fresnel2D(pattern.*MLARRAY,scale,1*fml,lambda); 55 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 56 | 57 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 58 | psf = pattern; 59 | LFpsf = f1; 60 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% -------------------------------------------------------------------------------- /PSFcalculation_calibration/estimate_aberration.m: -------------------------------------------------------------------------------- 1 | function zern_index = estimate_aberration(ideal_psf,experimental_psf,Nnum) % zernike index estimation of system aberration 2 | %% Input: 3 | % @ideal_psf: the maximum iteration number 4 | % @experimental_psf: the estimated volume 5 | % @Nnum: number of virtual pixels 6 | %% Ouput: 7 | % zern_index: zernike index estimation of system aberration 8 | % 9 | % [1] ZHI LU etc, 10 | % "A practical guide to scanning light-field microscopy with digital adaptive optics" 11 | % Nature Protocols, 2022 12 | 13 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 14 | % Date : 07/24/2021 15 | 16 | ideal_psf=padarray(ideal_psf,[(size(experimental_psf,1)-size(ideal_psf,1))/2, (size(experimental_psf,2)-size(ideal_psf,2))/2]); 17 | shift_kernel=zeros(Nnum,Nnum,2); 18 | for u=1:Nnum 19 | for v=1:Nnum 20 | if (u-round(Nnum/2))^2+(u-round(Nnum/2))^2<=36 21 | corr_map=normxcorr2(ideal_psf(:,:,u,v),experimental_psf(:,:,u,v)); % 2D correlation in the differernt spatial angular compnontes, respectively 22 | [testa,testb]=find(corr_map==max(corr_map(:))); 23 | shift_kernel(u,v,1)=testa-size(ideal_psf,1); 24 | shift_kernel(u,v,2)=testb-size(ideal_psf,2); 25 | end 26 | end 27 | end 28 | 29 | Nnum = 13; 30 | [Sx,Sy]=meshgrid([-fix(Nnum/2):fix(Nnum/2)],[-fix(Nnum/2):fix(Nnum/2)]); 31 | mask = (Sx.^2+Sy.^2)<=6^2; % maxmium frequency range 32 | shift_kernel(:,:,1) = shift_kernel(:,:,1).*mask; 33 | shift_kernel(:,:,2) = shift_kernel(:,:,2).*mask; 34 | 35 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 | %%%%%%%%%%%%%%%%%%%%%%% Integrating into wavefronts %%%%%%%%%%%%%%%%%%%%%%%%%%% 37 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 38 | waveShape = shift_kernel; 39 | waveShape(abs(waveShape)>=50) = 0; 40 | [Nnum,~] = size(waveShape); 41 | r_actual = 9.5; 42 | expand = 5; 43 | waveShape_expand = zeros(expand*Nnum,expand*Nnum,2); 44 | for idu = 1:Nnum 45 | for idv = 1:Nnum 46 | waveShape_expand((idu-1)*expand+1:idu*expand,(idv-1)*expand+1:idv*expand,1) = waveShape(idu,idv,1); 47 | waveShape_expand((idu-1)*expand+1:idu*expand,(idv-1)*expand+1:idv*expand,2) = waveShape(idu,idv,2); 48 | end 49 | end 50 | [xx,yy] = meshgrid(-(expand*size(waveShape,1)-1)/2:(expand*size(waveShape,1)-1)/2,... 51 | -(expand*size(waveShape,1)-1)/2:(expand*size(waveShape,1)-1)/2); 52 | mask = xx.^2+yy.^2<=((expand*r_actual/2).^2); 53 | waveShape_expand = waveShape_expand.*mask; 54 | waveShape_expand = waveShape_expand((end+1)/2-round(expand*r_actual/2):(end+1)/2+round(expand*r_actual/2),... 55 | (end+1)/2-round(expand*r_actual/2):(end+1)/2+round(expand*r_actual/2),:); 56 | 57 | ps = 100; 58 | 59 | [x1,y1] = meshgrid(1:size(waveShape_expand,1),1:size(waveShape_expand,2)); 60 | [x2,y2] = meshgrid(linspace(1,size(waveShape_expand,1),ps),linspace(1,size(waveShape_expand,1),ps)); 61 | 62 | calcu_dephase = zeros(ps,ps,2); 63 | calcu_dephase(:,:,1) = interp2(x1,y1,waveShape_expand(:,:,1),x2,y2,'nearest'); 64 | calcu_dephase(:,:,2) = interp2(x1,y1,waveShape_expand(:,:,2),x2,y2,'nearest'); 65 | 66 | maxIte = 1000; 67 | calcu_phase = intercircle(calcu_dephase,maxIte); 68 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 69 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 70 | 71 | 72 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 73 | %%%%%%%%%%%%%%%%%%%%%%%%%%%% Zernike index fitting %%%%%%%%%%%%%%%%%%%%%%%%%%%% 74 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 75 | [rr,cc] = size(calcu_phase); 76 | ra = (rr-1)/2; 77 | [xx,yy]=meshgrid([-ra:ra],[-ra:ra]); 78 | mask = xx.^2+yy.^2<=(ra^2); 79 | calcu_phase_k = -5.83*calcu_phase.*mask; 80 | 81 | x=linspace(-1,1,size(calcu_phase_k,1)); 82 | y=linspace(-1,1,size(calcu_phase_k,2)); 83 | xy=[x;y]; 84 | zern_index=lsqcurvefit('SH',zeros(1,21),xy,calcu_phase_k); 85 | zern_index(1:4)=0; 86 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 87 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 88 | end 89 | 90 | -------------------------------------------------------------------------------- /main_for_timelapse_zebrafish_embryo.m: -------------------------------------------------------------------------------- 1 | % Pre-processes and 3D reconstruciton demo with DAO (for time-lapse data) 2 | % The Code is created based on the method described in the following paper 3 | % [1] ZHI LU etc, 4 | % "A practical guide to scanning light-field microscopy with digital adaptive optics" 5 | % Nature Protocols, 2022 6 | % [2] JIAMIN WU, ZHI LU and DONG JIANG etc, 7 | % Iterative tomography with digital adaptive optics permits hour-long intravital observation of 3D subcellular dynamics at millisecond scale 8 | % Cell, 2021. 9 | % 10 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 11 | % Date : 10/01/2021 12 | 13 | clear; 14 | 15 | addpath('./Solver/'); 16 | addpath('./Util/'); 17 | 18 | % Preparameters 19 | GPUcompute=1; %% GPU accelerator (on/off) 20 | filepath='Data'; %% the filepath of raw scanning light field data, download from Google Drive (xxxx)!!!!!! 21 | Nnum=13; %% the number of sensor pixels after each microlens/ the number of angles in one dimension 22 | maxIter=1; %% the maximum iteration number of single frame 23 | time_weight_index=0.9; %% timeweighted coefficient, ranging from 0 to 1 24 | 25 | minFrame=0; %% the started frame 26 | maxFrame=80; %% the end frame 27 | Fstep=1; %% the spacing between adjacent frames 28 | 29 | 30 | % Auto-registration pixel realignment 31 | RawDir='Data'; 32 | [realignFolder,Nshift] = Auto_realignment(RawDir, Nnum);%% the sampling points of a single scanning period 33 | 34 | % PSF 35 | load('PSF/Calibrated_psf_M69.3_NA1.4_zmin-10u_zmax10u.mat'); 36 | weight=squeeze(sum(sum(sum(psf,1),2),5))./sum(psf(:)); 37 | weight=weight-min(weight(:)); 38 | weight=weight./max(weight(:)).*0.8; 39 | for u=1:Nnum 40 | for v=1:Nnum 41 | if (u-round(Nnum/2))^2+(v-round(Nnum/2))^2>(round(Nnum/3))^2 42 | weight(u,v)=0; 43 | end 44 | end 45 | end 46 | 47 | Fcount=minFrame; 48 | for frame = [minFrame: Fstep: maxFrame, maxFrame: -Fstep: minFrame] %% time-loop 49 | 50 | % Load spatial angular components 51 | WDF=zeros(183,183,Nnum,Nnum); 52 | for u=1:Nnum 53 | for v=1:Nnum 54 | tmp=single(imread(['Data_realign/embryo_3x3_300.0ms_Full_Hardware_LaserCount1_200404214338__0/realign/test_No',num2str(frame),'.tif'],(u-1)*Nnum+v)); 55 | WDF(:,:,u,v)=tmp(202:202+182,226:226+182); %% content-aware FOV 56 | end 57 | end 58 | % Time-weighted 59 | index_map=imread([num2str(Nshift),'x3.conf.sk.png']); 60 | index1=zeros(1,Nshift*Nshift); 61 | index2=zeros(1,Nshift*Nshift); 62 | for i=1:Nshift*Nshift 63 | [index1(i),index2(i)]=find(index_map==i-1); 64 | end 65 | WDF=time_weighted(WDF,time_weight_index,index1,index2,Nshift,Nnum,frame); 66 | 67 | 68 | % Initialization 69 | WDF=imresize(WDF,[size(WDF,1)*Nnum/Nshift,size(WDF,2)*Nnum/Nshift]); 70 | if frame==minFrame && Fcount==minFrame 71 | Xguess=ones(size(WDF,1),size(WDF,2),size(psf,5)); 72 | Xguess=Xguess./sum(Xguess(:)).*sum(WDF(:))./(size(WDF,3)*size(WDF,4)); 73 | else 74 | % replace the uniform initial value with the reconstructed result of the previous frame 75 | Xguess=0.5 .* (Xguess+ones(size(Xguess)).*sum(Xguess(:))./numel(Xguess)); 76 | end 77 | 78 | if Fcount==minFrame || Fcount==minFrame+Fstep 79 | DAO = 0; %% DAO off, when just <=2 frame were deconvolved in time-loop 80 | else 81 | DAO = 1; %% DAO on, after 2 frames were deconvolved in time-loop 82 | end 83 | Nb=1; %% Number of blocks for multi-site AO in one dimension 84 | 85 | % 3D deconvolution with DAO 86 | tic; 87 | Xguess = deconvRL_TimeSeries(maxIter, Xguess,WDF, psf,weight,DAO,Nb,GPUcompute); 88 | ttime = toc; 89 | disp([' Frame = ' num2str(frame) , ' took ', num2str(ttime), ' secs']); 90 | 91 | % save high-resolution reconstructed volume 92 | mkdir('Data_Recon3D/20200404_zebrafish_embryo'); 93 | if Fcount<=maxFrame 94 | % no need to save the middle results of time-loop algorithm 95 | % imwriteTFSK(single(gather(Xguess(26:end-25,26:end-25,11:end-10))),['Data_Recon3D/20200404_zebrafish_embryo/Frame',num2str(frame),'.tif']); %% crop volume edge and save it 96 | else 97 | imwriteTFSK(single(gather(Xguess(26:end-25,26:end-25,11:end-10))),['Data_Recon3D/20200404_zebrafish_embryo/Timeloop_Frame',num2str(frame),'.tif']); %% crop volume edge and save it 98 | end 99 | Fcount=Fcount+Fstep; 100 | end 101 | 102 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DAOSLIMIT Protocol 2 | 3 | Title: Supplementary Software for "A practical guide to scanning light-field microscopy with digital adaptive optics" 4 | 5 | Version: 2.0 6 | 7 | Copyright: 2021, ZHI LU, JIAMIN WU, QIONGHAI DAI 8 | 9 | Licence: GNU General Public License v2.0 10 | 11 | ---------------- 12 | 13 | If you use this code, please cite the companion paper where the original method appeared: 14 | 15 | Lu, Z. et al. A practical guide to scanning light-field microscopy with digital adaptive optics", Nature Protocols (2022). https://doi.org/10.1038/s41596-022-00703-9. 16 | 17 | For algorithmic details, please refer to our paper. 18 | 19 | The software and code are tested in Visual Studio 2015 and MATLAB 2018b (64 bit) under the MS Windows 10 64 bit version with an Intel i9-9980XE CPU, NVIDIA GeForce RTX 2080 Ti GPU and 128 GB RAM. 20 | 21 | Supporting and example data in this study and DLL files can be downloaded with the following link: https://drive.google.com/drive/folders/1zCXlDlkdB2lWyqny-jmcRhDHQwoql1FR?usp=sharing 22 | 23 | ---------------- 24 | How to use 25 | ---------------- 26 | 1. Unpack the package and install related framework 27 | 28 | 2. Open sLFdriver.exe to capture data 29 | 30 | a). The DLL files supporting OpenCV,OpenGL,NANOGUI,Andor SDK3 and LabVIEW should be placed in the main folder. The files are too large So we upload them in the google drive described before. 31 | 32 | b). The raw data of the scanning light field would be stored in the folder of "Data". The detailed instructions can be found in Supplementary Manual 1 in our paper (Submitted to Nature Protocols, 2021). 33 | 34 | 2. Include subdirectory in your Matlab path 35 | 36 | 3. Run the demo code named main_for_timelapse_zebrafish_embryo.m 37 | 38 | a). The raw data of the scanning light field should be placed in the folder of "Data". We have provided an example data for testing, which is a time-lapse video of zebrafish embryo (63x/1.4NA oil immersion objective). The data are too large. So we upload them in the google drive described before. 39 | 40 | b). The PSF files in the format of .mat should be placed in the folder of "PSF". We provide a system PSF calibration method. Readers can also generate the simulated ideal PSFs by running "main_computePSF_with_calibration.m" (based on wave optics theory [1], phase-space theory [2] and DAO algorithm [3]), which is located in the folder of "PSFcalculation_calibration". 41 | 42 | 43 | ---------------- 44 | Main modules description 45 | ---------------- 46 | 1. sLF_driver.exe: acquisition software for sLFM (>=50 GB memory, GPU) 47 | 48 | 2. main_for_timelapse_zebrafish_embryos.m: Pre-processes and 3D reconstruciton with DAO, time-weighted algorithm and time-loop algorithm (for time-lapse data)(>=50 GB memory) 49 | 50 | * Pre-processes including pixel realignment with system-error auto-correction, are involved in /Solve/Auto_realignment.m, which calls Realign.exe in main folder. 51 | 52 | ---------------- 53 | Configuration files description 54 | ---------------- 55 | 1. DLL files: including dll files of OpenCV,OpenGL,NANOGUI,Andor SDK3 and LabVIEW, used for sLFdriver.exe and Realign.exe. The NIControl.dll was built from LabVIEW 2019. If another version of LabVIEW is used or if a different type of NI box is used, the user may need to modify and rebuild the project. NI project source codes are available in 'NI_codes' folder. When rebuilding the project, launch 'NI_codes/proj/NIController.lvproj' and build FinalDll. Then copy NIControl.dll from 'NI_codes/builds/scanProj/NIConrtolVersion2' to the main folder. 56 | 57 | 2. Configuration files: 3x3.conf.sk.png, 5x5.conf.sk.png, 13x13.conf.sk.png, represent different scanning patterns used for pixel-realignment. 58 | SLFConfig.ini, includes the initial acquisition parameters. 59 | 60 | 3. Zemax files: for other microscopes from different companies, slight optimization of the distances between the lenses can be conducted in the Zemax (for details, see Supplementary Manual 2). 61 | 62 | ---------------- 63 | IMPORTANT NOTE 64 | ---------------- 65 | Should you have any questions regarding this code and the corresponding results, please contact Zhi Lu (luz18@mails.tsinghua.edu.cn). 66 | 67 | Reference: 68 | 1. R. Prevedel, Y.-G. Yoon, M. Hoffmann, N. Pak, G. Wetzstein, S. Kato, T. Schr?del, R. Raskar, M. Zimmer, E. S. Boyden, and A. Vaziri, 69 | "Simultaneous whole-animal 3D imaging of neuronal activity using light-field microscopy," Nature Methods, 2014, 11(7): 727-730. 70 | 2. Lu Z, Wu J, Qiao H, et al. "Phase-space deconvolution for light field microscopy," Optics express, 2019, 27(13): 18131-18145. 71 | 3. Wu J, Lu Z, Jiang D, et al. "Iterative tomography with digital adaptive optics permits hour-long intravital observation of 3D subcellular dynamics at millisecond scale" Cell, 2021, 184(12). 72 | 73 | -------------------------------------------------------------------------------- /PSFcalculation_calibration/zernfun.m: -------------------------------------------------------------------------------- 1 | function z = zernfun(n,m,r,theta,nflag) 2 | %ZERNFUN Zernike functions of order N and frequency M on the unit circle. 3 | % Z = ZERNFUN(N,M,R,THETA) returns the Zernike functions of order N 4 | % and angular frequency M, evaluated at positions (R,THETA) on the 5 | % unit circle. N is a vector of positive integers (including 0), and 6 | % M is a vector with the same number of elements as N. Each element 7 | % k of M must be a positive integer, with possible values M(k) = -N(k) 8 | % to +N(k) in steps of 2. R is a vector of numbers between 0 and 1, 9 | % and THETA is a vector of angles. R and THETA must have the same 10 | % length. The output Z is a matrix with one column for every (N,M) 11 | % pair, and one row for every (R,THETA) pair. 12 | % 13 | % Z = ZERNFUN(N,M,R,THETA,'norm') returns the normalized Zernike 14 | % functions. The normalization factor sqrt((2-delta(m,0))*(n+1)/pi), 15 | % with delta(m,0) the Kronecker delta, is chosen so that the integral 16 | % of (r * [Znm(r,theta)]^2) over the unit circle (from r=0 to r=1, 17 | % and theta=0 to theta=2*pi) is unity. For the non-normalized 18 | % polynomials, max(Znm(r=1,theta))=1 for all [n,m]. 19 | % 20 | % The Zernike functions are an orthogonal basis on the unit circle. 21 | % They are used in disciplines such as astronomy, optics, and 22 | % optometry to describe functions on a circular domain. 23 | % 24 | % The following table lists the first 15 Zernike functions. 25 | % 26 | % n m Zernike function Normalization 27 | % ---------------------------------------------------- 28 | % 0 0 1 1/sqrt(pi) 29 | % 1 1 r * cos(theta) 2/sqrt(pi) 30 | % 1 -1 r * sin(theta) 2/sqrt(pi) 31 | % 2 2 r^2 * cos(2*theta) sqrt(6/pi) 32 | % 2 0 (2*r^2 - 1) sqrt(3/pi) 33 | % 2 -2 r^2 * sin(2*theta) sqrt(6/pi) 34 | % 3 3 r^3 * cos(3*theta) sqrt(8/pi) 35 | % 3 1 (3*r^3 - 2*r) * cos(theta) sqrt(8/pi) 36 | % 3 -1 (3*r^3 - 2*r) * sin(theta) sqrt(8/pi) 37 | % 3 -3 r^3 * sin(3*theta) sqrt(8/pi) 38 | % 4 4 r^4 * cos(4*theta) sqrt(10/pi) 39 | % 4 2 (4*r^4 - 3*r^2) * cos(2*theta) sqrt(10/pi) 40 | % 4 0 6*r^4 - 6*r^2 + 1 sqrt(5/pi) 41 | % 4 -2 (4*r^4 - 3*r^2) * sin(2*theta) sqrt(10/pi) 42 | % 4 -4 r^4 * sin(4*theta) sqrt(10/pi) 43 | % ---------------------------------------------------- 44 | % 45 | % Example 1: 46 | % 47 | % % Display the Zernike function Z(n=5,m=1) 48 | % x = -1:0.01:1; 49 | % [X,Y] = meshgrid(x,x); 50 | % [theta,r] = cart2pol(X,Y); 51 | % idx = r<=1; 52 | % z = nan(size(X)); 53 | % z(idx) = zernfun(5,1,r(idx),theta(idx)); 54 | % figure 55 | % pcolor(x,x,z), shading interp 56 | % axis square, colorbar 57 | % title('Zernike function Z_5^1(r,\theta)') 58 | % 59 | % Example 2: 60 | % 61 | % % Display the first 10 Zernike functions 62 | % x = -1:0.01:1; 63 | % [X,Y] = meshgrid(x,x); 64 | % [theta,r] = cart2pol(X,Y); 65 | % idx = r<=1; 66 | % z = nan(size(X)); 67 | % n = [0 1 1 2 2 2 3 3 3 3]; 68 | % m = [0 -1 1 -2 0 2 -3 -1 1 3]; 69 | % Nplot = [4 10 12 16 18 20 22 24 26 28]; 70 | % y = zernfun(n,m,r(idx),theta(idx)); 71 | % figure('Units','normalized') 72 | % for k = 1:10 73 | % z(idx) = y(:,k); 74 | % subplot(4,7,Nplot(k)) 75 | % pcolor(x,x,z), shading interp 76 | % set(gca,'XTick',[],'YTick',[]) 77 | % axis square 78 | % title(['Z_{' num2str(n(k)) '}^{' num2str(m(k)) '}']) 79 | % end 80 | % 81 | % See also ZERNPOL, ZERNFUN2. 82 | % Paul Fricker 2/28/2012 83 | % Check and prepare the inputs: 84 | % ----------------------------- 85 | if ( ~any(size(n)==1) ) || ( ~any(size(m)==1) ) 86 | error('zernfun:NMvectors','N and M must be vectors.') 87 | end 88 | if length(n)~=length(m) 89 | error('zernfun:NMlength','N and M must be the same length.') 90 | end 91 | n = n(:); 92 | m = m(:); 93 | if any(mod(n-m,2)) 94 | error('zernfun:NMmultiplesof2', ... 95 | 'All N and M must differ by multiples of 2 (including 0).') 96 | end 97 | if any(m>n) 98 | error('zernfun:MlessthanN', ... 99 | 'Each M must be less than or equal to its corresponding N.') 100 | end 101 | if any( r>1 | r<0 ) 102 | error('zernfun:Rlessthan1','All R must be between 0 and 1.') 103 | end 104 | if ( ~any(size(r)==1) ) || ( ~any(size(theta)==1) ) 105 | error('zernfun:RTHvector','R and THETA must be vectors.') 106 | end 107 | r = r(:); 108 | theta = theta(:); 109 | length_r = length(r); 110 | if length_r~=length(theta) 111 | error('zernfun:RTHlength', ... 112 | 'The number of R- and THETA-values must be equal.') 113 | end 114 | % Check normalization: 115 | % -------------------- 116 | if nargin==5 && ischar(nflag) 117 | isnorm = strcmpi(nflag,'norm'); 118 | if ~isnorm 119 | error('zernfun:normalization','Unrecognized normalization flag.') 120 | end 121 | else 122 | isnorm = false; 123 | end 124 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 125 | % Compute the Zernike Polynomials 126 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 127 | % Determine the required powers of r: 128 | % ----------------------------------- 129 | m_abs = abs(m); 130 | rpowers = []; 131 | for j = 1:length(n) 132 | rpowers = [rpowers m_abs(j):2:n(j)]; 133 | end 134 | rpowers = unique(rpowers); 135 | % Pre-compute the values of r raised to the required powers, 136 | % and compile them in a matrix: 137 | % ----------------------------- 138 | if rpowers(1)==0 139 | rpowern = arrayfun(@(p)r.^p,rpowers(2:end),'UniformOutput',false); 140 | rpowern = cat(2,rpowern{:}); 141 | rpowern = [ones(length_r,1) rpowern]; 142 | else 143 | rpowern = arrayfun(@(p)r.^p,rpowers,'UniformOutput',false); 144 | rpowern = cat(2,rpowern{:}); 145 | end 146 | % Compute the values of the polynomials: 147 | % -------------------------------------- 148 | z = zeros(length_r,length(n)); 149 | for j = 1:length(n) 150 | s = 0:(n(j)-m_abs(j))/2; 151 | pows = n(j):-2:m_abs(j); 152 | for k = length(s):-1:1 153 | p = (1-2*mod(s(k),2))* ... 154 | prod(2:(n(j)-s(k)))/ ... 155 | prod(2:s(k))/ ... 156 | prod(2:((n(j)-m_abs(j))/2-s(k)))/ ... 157 | prod(2:((n(j)+m_abs(j))/2-s(k))); 158 | idx = (pows(k)==rpowers); 159 | z(:,j) = z(:,j) + p*rpowern(:,idx); 160 | end 161 | 162 | if isnorm 163 | z(:,j) = z(:,j)*sqrt((1+(m(j)~=0))*(n(j)+1)/pi); 164 | end 165 | end 166 | % END: Compute the Zernike Polynomials 167 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 168 | % Compute the Zernike functions: 169 | % ------------------------------ 170 | idx_pos = m>0; 171 | idx_neg = m<0; 172 | if any(idx_pos) 173 | z(:,idx_pos) = z(:,idx_pos).*cos(theta*m_abs(idx_pos)'); 174 | end 175 | if any(idx_neg) 176 | z(:,idx_neg) = z(:,idx_neg).*sin(theta*m_abs(idx_neg)'); 177 | end 178 | % EOF zernfun -------------------------------------------------------------------------------- /Solver/deconvRL_TimeSeries.m: -------------------------------------------------------------------------------- 1 | function Xguess = deconvRL_TimeSeries(maxIter, Xguess,WDF, psf,weight,DAO,Nb,GPUcompute) 2 | % Deconvolution for the time-series multiplexed phase-space data 3 | %% Input: 4 | % @maxIter: the maximum iteration number 5 | % @Xguess: the estimated volume 6 | % @WDF: multiplexed phase-space data 7 | % @psf: phase-space PSF 8 | % @weight: the weight numbers corresponding to the all spatial frequencies 9 | % @AO: digital adaptive optics on/off 10 | % @GPUcompute: GPU on/off 11 | %% Ouput: 12 | % output: the high resolution 3D volume by deconvolution 13 | % 14 | % [1] ZHI LU etc, 15 | % "A practical guide to scanning light-field microscopy with digital adaptive optics" 16 | % Nature Protocols, 2022 17 | % [2] JIAMIN WU, ZHI LU and DONG JIANG etc, 18 | % Iterative tomography with digital adaptive optics permits hour-long intravital observation of 3D subcellular dynamics at millisecond scale 19 | % Cell, 2021. 20 | 21 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 22 | % Date : 10/01/2021 23 | 24 | Nnum=size(psf,3); %% number of virtual pixels 25 | if GPUcompute==1 %% GPU on 26 | WDF = gpuArray(single(WDF)); 27 | weight=gpuArray(single(weight)); 28 | Xguess=gpuArray(single(Xguess)); 29 | end 30 | 31 | % 3D deconvolution order 32 | [index1,index2] = angle_order(Nnum); 33 | 34 | % iteractive DAO deconvolution algorithm 35 | for iter=1:maxIter 36 | % Digital adaptive optics to estimate aberration 37 | if DAO>0 % DAO on 38 | sidelobe=round(0.04*size(WDF,1)); %% reserved image border 39 | map_wavshape=zeros(Nnum,Nnum,Nb,Nb,2); 40 | Sb=fix( 0.9*size(WDF,1)/(Nb)/2 )*2+1; 41 | if Sb<50 42 | error('Pixel number of single block for multi-AO is too small.'); 43 | end 44 | border=(size(WDF,1)-Sb*Nb)/2; 45 | weight_mask=single(im2bw(gather(weight),1e-5)); 46 | [Sx,Sy]=meshgrid(-fix(Nnum/2):fix(Nnum/2),-fix(Nnum/2):fix(Nnum/2)); 47 | if iter>0 48 | for i=1:Nnum*Nnum 49 | u=index1(i); 50 | v=index2(i); 51 | if weight(u,v)==0 52 | continue; 53 | else 54 | if GPUcompute==1 55 | psf_uv=gpuArray(single(squeeze(psf(:,:,u,v,:)))); 56 | forwardFUN = @(Xguess) forwardProjectGPU( psf_uv, Xguess ); 57 | else 58 | psf_uv=single(squeeze(psf(:,:,u,v,:))); 59 | forwardFUN = @(Xguess) forwardProjectACC( psf_uv, Xguess ); 60 | end 61 | HXguess=forwardFUN(Xguess); 62 | 63 | % spatial partition to estimate wavefronts 64 | for uu=1:Nb 65 | for vv=1:Nb 66 | % tiled correlation with partitioning 67 | sub_HXguess=HXguess(border+(uu-1)*Sb+1:border+uu*Sb,border+(vv-1)*Sb+1:border+vv*Sb); 68 | sub_WDF=WDF(border+(uu-1)*Sb+1-sidelobe:border+uu*Sb+sidelobe,border+(vv-1)*Sb+1-sidelobe:border+vv*Sb+sidelobe,u,v); 69 | corr_map=gather(normxcorr2(sub_HXguess,sub_WDF)); 70 | [testa,testb]=find(corr_map==max(corr_map(:))); 71 | map_wavshape(u,v,uu,vv,1)=testa-size(sub_WDF,1)+sidelobe; 72 | map_wavshape(u,v,uu,vv,2)=testb-size(sub_WDF,2)+sidelobe; 73 | end 74 | end 75 | for uu=1:Nb 76 | for vv=1:Nb 77 | cx=map_wavshape(7,7,uu,vv,1); 78 | cy=map_wavshape(7,7,uu,vv,2); 79 | map_wavshape(:,:,uu,vv,1)=(squeeze(map_wavshape(:,:,uu,vv,1))-cx).*weight_mask; 80 | map_wavshape(:,:,uu,vv,2)=(squeeze(map_wavshape(:,:,uu,vv,2))-cy).*weight_mask; 81 | end 82 | end 83 | for uu=1:Nb 84 | for vv=1:Nb 85 | for u=1:Nnum 86 | for v=1:Nnum 87 | map_wavshape(u,v,uu,vv,1)=min(max(map_wavshape(u,v,uu,vv,1),-sidelobe),sidelobe);%% limit the shifted range 88 | map_wavshape(u,v,uu,vv,2)=min(max(map_wavshape(u,v,uu,vv,2),-sidelobe),sidelobe); 89 | end 90 | end 91 | end 92 | end 93 | % remove Zernike defocus items from wavefronts 94 | for uu=1:Nb 95 | for vv=1:Nb 96 | k1 = Sy.*squeeze(map_wavshape(:,:,uu,vv,1))+Sx.*squeeze(map_wavshape(:,:,uu,vv,2)); 97 | k2 = Sx.*Sx+Sy.*Sy; 98 | k=sum(k1(:))/sum(k2(:)); 99 | map_wavshape(:,:,uu,vv,1)=squeeze(map_wavshape(:,:,uu,vv,1))-k*Sy; 100 | map_wavshape(:,:,uu,vv,2)=squeeze(map_wavshape(:,:,uu,vv,2))-k*Sx; 101 | for u=1:Nnum 102 | for v=1:Nnum 103 | map_wavshape(u,v,uu,vv,1)=min(max(map_wavshape(u,v,uu,vv,1),-sidelobe),sidelobe); 104 | map_wavshape(u,v,uu,vv,2)=min(max(map_wavshape(u,v,uu,vv,2),-sidelobe),sidelobe); 105 | end 106 | end 107 | end 108 | end 109 | end 110 | end 111 | end 112 | end 113 | 114 | % Volume update 115 | for i=1:Nnum*Nnum 116 | u=index1(i); 117 | v=index2(i); 118 | if weight(u,v)==0 119 | continue; 120 | else 121 | if DAO>0 122 | % correct aberration 123 | map_wavshape_x=squeeze(map_wavshape(u,v,:,:,1)); 124 | map_wavshape_y=squeeze(map_wavshape(u,v,:,:,2)); 125 | map_wavshape_x1=imresize(map_wavshape_x,[round(size(WDF,1)/3),round(size(WDF,2)/3)],'nearest'); 126 | map_wavshape_y1=imresize(map_wavshape_y,[round(size(WDF,1)/3),round(size(WDF,2)/3)],'nearest'); 127 | map_wavshape_xx=imresize(map_wavshape_x1,[size(WDF,1),size(WDF,2)],'cubic'); 128 | map_wavshape_yy=imresize(map_wavshape_y1,[size(WDF,1),size(WDF,2)],'cubic'); 129 | [coordinate1,coordinate2]=meshgrid(1:size(WDF,1),1:size(WDF,2)); 130 | if GPUcompute==1 131 | WDF_uv=gpuArray(interp2(coordinate1,coordinate2,WDF(:,:,u,v),coordinate1+map_wavshape_yy,coordinate2+map_wavshape_xx,'cubic',0)); 132 | else 133 | WDF_uv=interp2(coordinate1,coordinate2,WDF(:,:,u,v),coordinate1+map_wavshape_yy,coordinate2+map_wavshape_xx,'cubic',0); 134 | end 135 | else 136 | WDF_uv=WDF(:,:,u,v); 137 | end 138 | if GPUcompute==1 139 | psf_uv=single(squeeze(psf(:,:,u,v,:))); 140 | forwardFUN = @(Xguess) forwardProjectGPU( psf_uv, Xguess ); 141 | backwardFUN = @(projection) backwardProjectGPU(psf_uv, projection ); 142 | uniform_matrix = gpuArray(single (ones( size(WDF,1),size(WDF,2) ))); 143 | else 144 | psf_uv=single(squeeze(psf(:,:,u,v,:))); 145 | forwardFUN = @(Xguess) forwardProjectACC( psf_uv, Xguess ); 146 | backwardFUN = @(projection) backwardProjectACC(psf_uv, projection ); 147 | uniform_matrix = single (ones( size(WDF,1),size(WDF,2) )); 148 | end 149 | % RL deconvolution 150 | HXguess=forwardFUN(Xguess); 151 | errorEM=squeeze(WDF_uv)./HXguess; 152 | errorEM(~isfinite(errorEM))=0; 153 | XguessCor = backwardFUN(errorEM) ; 154 | Htf=backwardFUN( uniform_matrix ); 155 | Htf(Htf<1e-4)=0; 156 | Xguess_add=Xguess.*XguessCor./Htf; 157 | clear Htf;clear XguessCor; 158 | Xguess_add(find(isnan(Xguess_add))) = 0; 159 | Xguess_add(find(isinf(Xguess_add))) = 0; 160 | Xguess_add(Xguess_add<0 ) = 0; 161 | Xguess=Xguess_add.*weight(u,v)+(1-weight(u,v)).*Xguess; 162 | clear Xguess_add; 163 | Xguess(find(isnan(Xguess))) = 0; 164 | Xguess(Xguess<1e-4 ) = 1e-4; 165 | end 166 | end 167 | 168 | end 169 | -------------------------------------------------------------------------------- /Solver/deconvRL.m: -------------------------------------------------------------------------------- 1 | function Xguess = deconvRL(maxIter, Xguess,WDF, psf,weight,DAO,Nb,GPUcompute) 2 | % Deconvolution for the single-frame multiplexed phase-space data 3 | %% Input: 4 | % @maxIter: the maximum iteration number 5 | % @Xguess: the estimated volume 6 | % @WDF: multiplexed phase-space data 7 | % @psf: phase-space PSF 8 | % @weight: the weight numbers corresponding to the all spatial frequencies 9 | % @AO: digital adaptive optics on/off 10 | % @GPUcompute: GPU on/off 11 | %% Ouput: 12 | % output: the high resolution 3D volume by deconvolution 13 | % 14 | % [1] ZHI LU etc, 15 | % "A practical guide to scanning light-field microscopy with digital adaptive optics" 16 | % Nature Protocols, 2022 17 | % [2] JIAMIN WU, ZHI LU and DONG JIANG etc, 18 | % Iterative tomography with digital adaptive optics permits hour-long intravital observation of 3D subcellular dynamics at millisecond scale 19 | % Cell, 2021. 20 | 21 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 22 | % Date : 10/01/2021 23 | 24 | Nnum=size(psf,3); %% number of virtual pixels 25 | if GPUcompute==1 %% GPU on 26 | WDF = gpuArray(single(WDF)); 27 | weight=gpuArray(single(weight)); 28 | Xguess=gpuArray(single(Xguess)); 29 | end 30 | 31 | % 3D deconvolution order 32 | [index1,index2] = angle_order(Nnum); 33 | 34 | % iteractive DAO deconvolution algorithm 35 | for iter=1:maxIter 36 | tic; 37 | % Digital adaptive optics to estimate aberration 38 | if DAO>0 % DAO on 39 | sidelobe=round(0.04*size(WDF,1)); %% reserved image border 40 | map_wavshape=zeros(Nnum,Nnum,Nb,Nb,2); 41 | Sb=fix( 0.9*size(WDF,1)/(Nb)/2 )*2+1; 42 | if Sb<50 43 | error('Pixel number of single block for multi-AO is too small.'); 44 | end 45 | border=(size(WDF,1)-Sb*Nb)/2; 46 | weight_mask=single(im2bw(gather(weight),1e-5)); 47 | [Sx,Sy]=meshgrid(-fix(Nnum/2):fix(Nnum/2),-fix(Nnum/2):fix(Nnum/2)); 48 | if iter>1 49 | for i=1:Nnum*Nnum 50 | u=index1(i); 51 | v=index2(i); 52 | if weight(u,v)==0 53 | continue; 54 | else 55 | if GPUcompute==1 56 | psf_uv=gpuArray(single(squeeze(psf(:,:,u,v,:)))); 57 | forwardFUN = @(Xguess) forwardProjectGPU( psf_uv, Xguess ); 58 | else 59 | psf_uv=single(squeeze(psf(:,:,u,v,:))); 60 | forwardFUN = @(Xguess) forwardProjectACC( psf_uv, Xguess ); 61 | end 62 | HXguess=forwardFUN(Xguess); 63 | 64 | % spatial partition to estimate wavefronts 65 | for uu=1:Nb 66 | for vv=1:Nb 67 | % tiled correlation with partitioning 68 | sub_HXguess=HXguess(border+(uu-1)*Sb+1:border+uu*Sb,border+(vv-1)*Sb+1:border+vv*Sb); 69 | sub_WDF=WDF(border+(uu-1)*Sb+1-sidelobe:border+uu*Sb+sidelobe,border+(vv-1)*Sb+1-sidelobe:border+vv*Sb+sidelobe,u,v); 70 | corr_map=gather(normxcorr2(sub_HXguess,sub_WDF)); 71 | [testa,testb]=find(corr_map==max(corr_map(:))); 72 | map_wavshape(u,v,uu,vv,1)=testa-size(sub_WDF,1)+sidelobe; 73 | map_wavshape(u,v,uu,vv,2)=testb-size(sub_WDF,2)+sidelobe; 74 | end 75 | end 76 | for uu=1:Nb 77 | for vv=1:Nb 78 | cx=map_wavshape(7,7,uu,vv,1); 79 | cy=map_wavshape(7,7,uu,vv,2); 80 | map_wavshape(:,:,uu,vv,1)=(squeeze(map_wavshape(:,:,uu,vv,1))-cx).*weight_mask; 81 | map_wavshape(:,:,uu,vv,2)=(squeeze(map_wavshape(:,:,uu,vv,2))-cy).*weight_mask; 82 | end 83 | end 84 | for uu=1:Nb 85 | for vv=1:Nb 86 | for u=1:Nnum 87 | for v=1:Nnum 88 | map_wavshape(u,v,uu,vv,1)=min(max(map_wavshape(u,v,uu,vv,1),-sidelobe),sidelobe);%% limit the shifted range 89 | map_wavshape(u,v,uu,vv,2)=min(max(map_wavshape(u,v,uu,vv,2),-sidelobe),sidelobe); 90 | end 91 | end 92 | end 93 | end 94 | % remove Zernike defocus items from wavefronts 95 | for uu=1:Nb 96 | for vv=1:Nb 97 | k1 = Sy.*squeeze(map_wavshape(:,:,uu,vv,1))+Sx.*squeeze(map_wavshape(:,:,uu,vv,2)); 98 | k2 = Sx.*Sx+Sy.*Sy; 99 | k=sum(k1(:))/sum(k2(:)); 100 | map_wavshape(:,:,uu,vv,1)=squeeze(map_wavshape(:,:,uu,vv,1))-k*Sy; 101 | map_wavshape(:,:,uu,vv,2)=squeeze(map_wavshape(:,:,uu,vv,2))-k*Sx; 102 | for u=1:Nnum 103 | for v=1:Nnum 104 | map_wavshape(u,v,uu,vv,1)=min(max(map_wavshape(u,v,uu,vv,1),-sidelobe),sidelobe); 105 | map_wavshape(u,v,uu,vv,2)=min(max(map_wavshape(u,v,uu,vv,2),-sidelobe),sidelobe); 106 | end 107 | end 108 | end 109 | end 110 | end 111 | end 112 | end 113 | end 114 | 115 | % Volume update 116 | for i=1:Nnum*Nnum 117 | u=index1(i); 118 | v=index2(i); 119 | if weight(u,v)==0 120 | continue; 121 | else 122 | if DAO>0 && iter>1 123 | % correct aberration 124 | map_wavshape_x=squeeze(map_wavshape(u,v,:,:,1)); 125 | map_wavshape_y=squeeze(map_wavshape(u,v,:,:,2)); 126 | map_wavshape_x1=imresize(map_wavshape_x,[round(size(WDF,1)/3),round(size(WDF,2)/3)],'nearest'); 127 | map_wavshape_y1=imresize(map_wavshape_y,[round(size(WDF,1)/3),round(size(WDF,2)/3)],'nearest'); 128 | map_wavshape_xx=imresize(map_wavshape_x1,[size(WDF,1),size(WDF,2)],'cubic'); 129 | map_wavshape_yy=imresize(map_wavshape_y1,[size(WDF,1),size(WDF,2)],'cubic'); 130 | [coordinate1,coordinate2]=meshgrid(1:size(WDF,1),1:size(WDF,2)); 131 | if GPUcompute==1 132 | WDF_uv=gpuArray(interp2(coordinate1,coordinate2,WDF(:,:,u,v),coordinate1+map_wavshape_yy,coordinate2+map_wavshape_xx,'cubic',0)); 133 | else 134 | WDF_uv=interp2(coordinate1,coordinate2,WDF(:,:,u,v),coordinate1+map_wavshape_yy,coordinate2+map_wavshape_xx,'cubic',0); 135 | end 136 | else 137 | WDF_uv=WDF(:,:,u,v); 138 | end 139 | if GPUcompute==1 140 | psf_uv=gpuArray(single(squeeze(psf(:,:,u,v,:)))); 141 | forwardFUN = @(Xguess) forwardProjectGPU( psf_uv, Xguess ); 142 | backwardFUN = @(projection) backwardProjectGPU(psf_uv, projection ); 143 | uniform_matrix = gpuArray(single (ones( size(WDF,1),size(WDF,2) ))); 144 | else 145 | psf_uv=single(squeeze(psf(:,:,u,v,:))); 146 | forwardFUN = @(Xguess) forwardProjectACC( psf_uv, Xguess ); 147 | backwardFUN = @(projection) backwardProjectACC(psf_uv, projection ); 148 | uniform_matrix = single (ones( size(WDF,1),size(WDF,2) )); 149 | end 150 | % RL deconvolution 151 | HXguess=forwardFUN(Xguess); 152 | errorEM=squeeze(WDF_uv)./HXguess; 153 | errorEM(~isfinite(errorEM))=0; 154 | XguessCor = backwardFUN(errorEM) ; 155 | Htf=backwardFUN( uniform_matrix ); 156 | Htf(Htf<1e-4)=0; 157 | Xguess_add=Xguess.*XguessCor./Htf; 158 | clear Htf;clear XguessCor; 159 | Xguess_add(find(isnan(Xguess_add))) = 0; 160 | Xguess_add(find(isinf(Xguess_add))) = 0; 161 | Xguess_add(Xguess_add<0 ) = 0; 162 | Xguess=Xguess_add.*weight(u,v)+(1-weight(u,v)).*Xguess; 163 | clear Xguess_add; 164 | Xguess(find(isnan(Xguess))) = 0; 165 | Xguess(Xguess<1e-4)=1e-4; 166 | end 167 | end 168 | ttime = toc; 169 | disp([' iter ' num2str(iter) ' | ' num2str(maxIter),', took ' num2str(ttime) ' secs']); 170 | % imwriteTFSK(gather(Xguess),['AO1_2/iter',num2str(iter),'.tif']); 171 | end 172 | -------------------------------------------------------------------------------- /Solver/Auto_realignment.m: -------------------------------------------------------------------------------- 1 | function [realignFolderSub, Nshift]=Auto_realignment(RawDir, Nnum) 2 | % Auto-registration preprocess for correcting system-error pixel-realignment 3 | % 4 | % The Code is created based on the method described in the following paper 5 | % [1] ZHI LU etc, 6 | % "A practical guide to scanning light-field microscopy with digital adaptive optics" 7 | % Nature Protocols, 2022 8 | % 9 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 10 | % Date : 07/24/2021 11 | 12 | rotation = 0; % Angle of clockwise rotation of scanning light field images 13 | preResize = 0.9995; % Scanning light field images resizing scale (The default value is 1) 14 | autoCenterMode = 1; % Automatic identification for the center point of light field (on/off) 15 | 16 | dirOutput=dir(fullfile(RawDir,'*.0.tiff')); % information of rawdata 17 | source={dirOutput.name}'; % filename list of rawdata 18 | 19 | for sourceIdx = 1:size(source,1) 20 | if(source{sourceIdx}(end - 8) == 'C') 21 | continue; 22 | end 23 | try 24 | ticer = tic; 25 | front = source{sourceIdx}(1:end-6); 26 | dirOutput=dir(fullfile(RawDir,strcat(front, '*'))); 27 | this_name = {dirOutput.name}'; 28 | Itmp = imread(strcat(RawDir, '/',source{sourceIdx}), 1); 29 | [h,w] = size(Itmp); 30 | Nx = floor(w * preResize / (2*Nnum)) - 2; 31 | Ny = floor(h * preResize / (2*Nnum)) - 2; 32 | imgSize = h * w * 2; 33 | fileSizes = cell2mat({dirOutput.bytes}); 34 | imgCount = 0; 35 | for fileIdx = 1:size(fileSizes, 2) 36 | imgCount = imgCount + floor(fileSizes(fileIdx) / imgSize); 37 | end 38 | name = strcat(RawDir, '/',source{sourceIdx}); 39 | [laserCountIdxS, laserCountIdxE] = regexp(front, '(?<=_LaserCount)[^/]+(?=_)'); 40 | frameJump = str2num(front(laserCountIdxS:laserCountIdxE)); 41 | [shiftIdxS, shiftIdxE] = regexp(front, '(?<=_)[[0-9]]+(?=x)'); 42 | Nshift = str2num(front(shiftIdxS(end):shiftIdxE(end))); 43 | if(rotation == 0) 44 | confName = sprintf('./%dx%d.conf.sk.png', Nshift, Nshift); 45 | else 46 | confName = sprintf('./%dx%d.conf.sk.rot%d.png', Nshift, Nshift, rotation); 47 | end 48 | 49 | groupMode = 1; % "0": interval mode (for 1-9, 10-18,...); "1": sliding-window mode (for 1-9, 2-10,...) (The default value is 1) 50 | groupCount = floor(imgCount / frameJump); 51 | if(Nshift ~= 1) 52 | if(groupMode == 1) 53 | groupCount = groupCount - Nshift * Nshift + 1; 54 | else 55 | groupCount = floor(groupCount / (Nshift * Nshift)); 56 | end 57 | end 58 | clear centerviewList 59 | for startFrame = 0:frameJump - 1 60 | autoCenterFrame = startFrame; % The image frame used for center view identification 61 | realignFolder = strcat('Data_realign/',source{sourceIdx}(1:end-7), '__', num2str(startFrame)); 62 | mkdir(realignFolder); 63 | realignFolderSub = strcat(realignFolder,'/realign'); 64 | mkdir(realignFolderSub); 65 | realignName = strcat(realignFolderSub, '/test'); 66 | 67 | centerView = strcat(realignFolder, '/centerView.tiff'); 68 | 69 | 70 | centerviewList(startFrame+1, :) = strcat(centerView(1:end-4),'0.tif'); % TODO: now we only support .0.tif 71 | 72 | centerX=1024; % center point selection (x-direction) manually£¬invalid when autoCenterMode = 1 73 | centerY=1024; % center point selection (y-direction) manually£¬invalid when autoCenterMode = 1 74 | if(autoCenterMode == 1) 75 | [centerX, centerY, centerProb] = AutoCenter(imread(name, autoCenterFrame + 1), Nnum); 76 | else 77 | centerProb = 999; 78 | end 79 | WriteCenterPt(realignFolder, centerX, centerY, centerProb, imread(name, autoCenterFrame + 1)); 80 | addpath('./Util/'); 81 | 82 | realignMode = 'LZ'; % Default, no need to modify 83 | resize = 0; % "0": No upsampling; "1":Upsamping Nnum/Nshift times in spatial domain (The default value is 0) 84 | 85 | % pixel-realignment (c++ program) 86 | % ./ReAlign [CaptureNshift] [OutputFile] [RawData] 87 | % [RawDataIdx] [CenterPixelX] [CenterPixelY] 88 | % [PickLensSizeX] (DataGroup = 1) (GroupMode = 0){0=individual, 1=continues} (ShiftConfigFile = Auto) 89 | % (FrameJump = 1) (Resize = 1) (ResizeShift = 13) (PickLensSizeY = X) 90 | 91 | command = sprintf('ReAlign %d %s %s %d %d %d %d %d %d %s %d %d %d %d %s %s %d %f',... 92 | Nshift, realignName, name, startFrame, centerX, centerY, Nx,... 93 | groupCount, groupMode, confName, frameJump, resize, Nnum, Ny, realignMode, centerView, rotation, preResize); 94 | system(command); 95 | 96 | end 97 | LaserMergeOption = 1;%=1 means merging of all channels£¬=0 means no merging channels 98 | if(frameJump > 1 && LaserMergeOption ~= 0) 99 | fprintf('working on channel merge...\n'); 100 | channel = min([3, frameJump]); 101 | mergeView = uint16(zeros((Ny*2+1)*Nshift, (Nx*2+1)*Nshift, 3, groupCount)); 102 | outPath = strcat(source{sourceIdx}(1:end-7), '__merge'); 103 | mkdir(outPath); 104 | for frameIdx = 1:groupCount 105 | for channelIdx = 1:channel 106 | if(exist(centerviewList(channelIdx, :), 'file')) 107 | mergeView(:,:,channelIdx,frameIdx) = imread(centerviewList(channelIdx, :), frameIdx); 108 | end 109 | end 110 | end 111 | for channelIdx = 1:channel 112 | mergeView(:,:,channelIdx,:) = double(mergeView(:,:,channelIdx,:)) / double(max(max(max(max(mergeView(:,:,channelIdx,:)))))) * 255 * 2; 113 | end 114 | mergeView = uint8(mergeView); 115 | % imwrite time-lapse multi-color center view 116 | for frameIdx = 1:groupCount 117 | if(frameIdx == 1) 118 | imwrite(squeeze(mergeView(:,:,:,frameIdx)), strcat(outPath,'/centerViewMerge_channel.tif')); 119 | else 120 | imwrite(squeeze(mergeView(:,:,:,frameIdx)), strcat(outPath,'/centerViewMerge_channel.tif'), 'WriteMode', 'append'); 121 | end 122 | end 123 | end 124 | fprintf('Realign %s, frame count : %d, cost %f sec\n', source{sourceIdx}, groupCount, toc(ticer)); 125 | catch 126 | warning('we met some error!'); 127 | end 128 | end 129 | 130 | function [] = WriteCenterPt(path, CX, CY, prob, img) % write center view 131 | txt = fopen(strcat(path,'/CenterPoint.txt'), 'w'); 132 | fprintf(txt, 'X = %d\nY = %d\nprob = %.2f%%\n##Both (X,Y) in [0, N-1]', CX, CY, prob*100); 133 | fclose(txt); 134 | imwrite(img, strcat(path,'/UsedImg.tiff')); 135 | end 136 | 137 | function [Xcenter,Ycenter, prob] = AutoCenter(img, Nnum) % Automatic identification algorithm 138 | 139 | SUB_NUM = 3; % number of blocks 140 | SUB_MAX_RANGE_RATIO = 5; % pixels 141 | MAX_AREA_TRUST_RATIO = 4;% confidence 142 | img = double(img); 143 | fullX = size(img, 2); 144 | fullY = size(img, 1); 145 | 146 | ansList = zeros(1 + MAX_AREA_TRUST_RATIO + SUB_NUM*SUB_NUM, 3); 147 | fprintf('Full Image :'); 148 | [ansList(1,1), ansList(1,2), ansList(1,3)] = AutoCenterSub(img, Nnum, 0, 0); 149 | fprintf('\n'); 150 | maxImg = max(img(:)); 151 | [maxPosY, maxPosX] = find(img == maxImg); 152 | maxPosX = maxPosX(round(size(maxPosX, 1) / 2)); 153 | maxPosY = maxPosY(round(size(maxPosY, 1) / 2)); 154 | 155 | rangeSX = round(maxPosX - fullX / SUB_MAX_RANGE_RATIO); 156 | if(rangeSX < 1) rangeSX = 1; end 157 | rangeEX = round(maxPosX + fullX / SUB_MAX_RANGE_RATIO); 158 | if(rangeEX > fullX) rangeEX = fullX; end 159 | 160 | rangeSY = round(maxPosY - fullY / SUB_MAX_RANGE_RATIO); 161 | if(rangeSY < 1) rangeSY = 1; end 162 | rangeEY = round(maxPosY + fullY / SUB_MAX_RANGE_RATIO); 163 | if(rangeEY > fullY) rangeEY = fullY; end 164 | fprintf('Lightest x%d:', MAX_AREA_TRUST_RATIO); 165 | [ansList(2,1), ansList(2,2), ansList(2,3)] = ... 166 | AutoCenterSub(img(rangeSY : rangeEY, rangeSX : rangeEX), Nnum, rangeSX - 1, rangeSY - 1); 167 | fprintf('\n'); 168 | ansList(2:2+MAX_AREA_TRUST_RATIO-1, :) = repmat(ansList(2,:), [MAX_AREA_TRUST_RATIO, 1]); 169 | 170 | anchorPtX = zeros(SUB_NUM+1, 1); 171 | for i = 0:SUB_NUM 172 | anchorX = round(1 + i * fullX/SUB_NUM); 173 | if(anchorX > fullX) anchorX = fullX; end 174 | anchorPtX(i+1) = anchorX; 175 | end 176 | anchorPtY = zeros(SUB_NUM+1, 1); 177 | for i = 0:SUB_NUM 178 | anchorY = round(1 + i * fullY/SUB_NUM); 179 | if(anchorY > fullY) anchorY = fullY; end 180 | anchorPtY(i+1) = anchorY; 181 | end 182 | 183 | idx = 1 + MAX_AREA_TRUST_RATIO + 1; 184 | 185 | for i = 1:SUB_NUM % x direction 186 | for j = 1:SUB_NUM % y direction 187 | fprintf('Sub X=%d Y=%d:', i,j); 188 | [ansList(idx,1), ansList(idx,2), ansList(idx,3)] = ... 189 | AutoCenterSub(img(anchorPtY(j) : anchorPtY(j+1), anchorPtX(i) : anchorPtX(i+1)), Nnum, anchorPtX(i) - 1, anchorPtY(j) - 1); 190 | distance = sqrt((i - ((SUB_NUM + 1) /2))^2 + (j - ((SUB_NUM + 1) /2))^2); 191 | prob_loss = 1 - (distance / SUB_NUM); 192 | fprintf('prob loss ratio = %.2f\n', prob_loss); 193 | ansList(idx,3) = ansList(idx,3) * prob_loss; 194 | idx = idx + 1; 195 | end 196 | end 197 | savedAnsList = ansList; 198 | ansList(:,3) = ansList(:,3) / sum(ansList(:,3)); 199 | ansList(:,1) = ansList(:,1) .* ansList(:,3); 200 | ansList(:,2) = ansList(:,2) .* ansList(:,3); 201 | myAns = round([sum(ansList(:,1)), sum(ansList(:,2))]); 202 | prob = 0; 203 | probCount = 0; 204 | for i = 1:size(savedAnsList, 1) 205 | if(myAns == savedAnsList(i, 1:2)) 206 | probCount = probCount + 1; 207 | prob = prob + savedAnsList(i, 3); 208 | end 209 | end 210 | if(probCount ~= 0) 211 | prob = prob / probCount; 212 | end 213 | Xcenter = myAns(1) + floor(size(img,2) / Nnum / 2) * Nnum; 214 | Ycenter = myAns(2) + floor(size(img,1) / Nnum / 2) * Nnum; 215 | fprintf('AutoCenter found x = %d, y = %d (range from 0~[size-1]), credibility = %.2f%%, check at ImageJ\n', Xcenter, Ycenter, prob*100); 216 | end 217 | 218 | function [Xcenter, Ycenter, prob] = AutoCenterSub(img, Nnum, x_offset, y_offset) % Automatic identification algorithm in the sub-region 219 | 220 | BEST_RATIO = 0.3; 221 | WORST_RATIO = 0.9; 222 | 223 | img = double(img); 224 | img = img ./ max(img(:)); 225 | img = img.^2; 226 | kernal = fspecial('gaussian',[Nnum,Nnum],3); 227 | img = imfilter(img, kernal); 228 | locMatrix = zeros(Nnum, Nnum); 229 | for i = 1:Nnum 230 | for j = 1:Nnum 231 | picMat = img(i:Nnum:end, j:Nnum:end); 232 | avg = mean(mean(picMat)); 233 | picMat(picMat < avg) = 0; 234 | hugePos = find(picMat ~= 0); 235 | locMatrix(i,j) = sum(picMat(:)) / size(hugePos, 1); 236 | end 237 | end 238 | 239 | sumX = sum(locMatrix); 240 | sumY = sum(locMatrix,2); 241 | sumX = sumX + circshift(sumX, 1, 2); 242 | sumY = sumY + circshift(sumY, 1, 1); 243 | darkX = 1; 244 | for i = 1:Nnum 245 | if(sumX(i) < sumX(darkX)) 246 | darkX = i; 247 | end 248 | end 249 | darkY = 1; 250 | for i = 1:Nnum 251 | if(sumY(i) < sumY(darkY)) 252 | darkY = i; 253 | end 254 | end 255 | Xcenter = mod(darkX + floor(Nnum / 2) - 1 + x_offset, Nnum); 256 | Ycenter = mod(darkY + floor(Nnum / 2) - 1 + y_offset, Nnum); 257 | prob = (WORST_RATIO - min(min(locMatrix)) / max(max(locMatrix))) / (WORST_RATIO - BEST_RATIO); 258 | if(prob > 1) 259 | prob = 1; 260 | elseif(prob < 0) 261 | prob = 0; 262 | end 263 | fprintf('AutoCenterSub x = %d, y = %d, prob = %f ', Xcenter, Ycenter, prob); 264 | end 265 | 266 | 267 | 268 | 269 | end 270 | 271 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., 5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Lesser General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License along 307 | with this program; if not, write to the Free Software Foundation, Inc., 308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 309 | 310 | Also add information on how to contact you by electronic and paper mail. 311 | 312 | If the program is interactive, make it output a short notice like this 313 | when it starts in an interactive mode: 314 | 315 | Gnomovision version 69, Copyright (C) year name of author 316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 317 | This is free software, and you are welcome to redistribute it 318 | under certain conditions; type `show c' for details. 319 | 320 | The hypothetical commands `show w' and `show c' should show the appropriate 321 | parts of the General Public License. Of course, the commands you use may 322 | be called something other than `show w' and `show c'; they could even be 323 | mouse-clicks or menu items--whatever suits your program. 324 | 325 | You should also get your employer (if you work as a programmer) or your 326 | school, if any, to sign a "copyright disclaimer" for the program, if 327 | necessary. Here is a sample; alter the names: 328 | 329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 331 | 332 | , 1 April 1989 333 | Ty Coon, President of Vice 334 | 335 | This General Public License does not permit incorporating your program into 336 | proprietary programs. If your program is a subroutine library, you may 337 | consider it more useful to permit linking proprietary applications with the 338 | library. If this is what you want to do, use the GNU Lesser General 339 | Public License instead of this License. 340 | -------------------------------------------------------------------------------- /PSFcalculation_calibration/main_computePSF_with_calibration.m: -------------------------------------------------------------------------------- 1 | 2 | % The Code is created based on the method described in the following paper 3 | % [1] ZHI LU etc, 4 | % "A practical guide to scanning light-field microscopy with digital adaptive optics" 5 | % Nature Protocols, 2022 6 | % [2] JIAMIN WU, ZHI LU and DONG JIANG.etc, 7 | % "Iterative tomography with digital adaptive optics permits hour-long intravital observation of 3D subcellular dynamics at millisecond scale" 8 | % Cell, 2021. 9 | % [3] Robert Prevede, Young-Gyu Yoon, Maximilian Hoffmann, Nikita Pak.etc. 10 | % "Simultaneous whole-animal 3D imaging of neuronal activity using light-field microscopy " 11 | % in Nature Methods VOL.11 NO.7|July 2014. 12 | % The Code is modified and extended from Robert's code and Wu's code 13 | % 14 | % Contact: ZHI LU (luz18@mails.tsinghua.edu.cn) 15 | % Date : 07/24/2021 16 | 17 | clear; 18 | warning('off'); 19 | %%%%%%%%%%%%%%%%%%%%%%% SIM PARAMETERS %%%%%%%%%%%%%%%%%%%%%%%%%%% 20 | NA = 1.4; %% numerical aperture of objective 21 | MLPitch = 100*1e-6; %% pitch of the microlens 22 | Nnum = 13; %% number of virtual pixels 23 | OSR = 3; %% spatial oversampling ratio for computing PSF 24 | n = 1.515; %% refractive index 25 | fml = 2100e-6; %% focal length of the microlens pitch 26 | M = 69.3; %% magnification from sample to microlens array 27 | lambda = 525*1e-9; %% wavelength 28 | zmax = 10*1e-6; %% the axial location of the highest z-plane with respect to the focal plane 29 | zmin = -10*1e-6; %% the axial location of the lowest z-plane with respect to the focal plane 30 | zspacing = 0.2*1e-6; %% spacing between adjacent z-planes 31 | eqtol = 1e-10; 32 | k = 2*pi*n/lambda; %% k 33 | k0 = 2*pi*1/lambda; %% k 34 | ftl = 165e-3; %% focal length of tube lens 35 | fobj = ftl/M; %% focal length of objective lens 36 | fnum_obj = M/(2*NA); %% f-number of objective lens (imaging-side) 37 | fnum_ml = fml/MLPitch; %% f-number of micrl lens 38 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 39 | 40 | 41 | 42 | %%%%%%%%%%%%%% Generate ideal PSF %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 43 | %%%%%%%%%%%%% DEFINE OBJECT SPACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 44 | if mod(Nnum,2)==0, 45 | error(['Nnum should be an odd number']); 46 | end 47 | pixelPitch = MLPitch/Nnum; %% pitch of virtual pixels 48 | 49 | x1objspace = [0]; 50 | x2objspace = [0]; 51 | x3objspace = [1e-6]; % offset 52 | objspace = ones(length(x1objspace),length(x2objspace),length(x3objspace)); 53 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 54 | 55 | 56 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 57 | p3max = max(abs(x3objspace)); 58 | x1testspace = (pixelPitch/OSR)* [0:1: Nnum*OSR*60]; 59 | x2testspace = [0]; 60 | [psfLine] = calcPSFFT(p3max, fobj, NA, x1testspace, pixelPitch/OSR, lambda, fml, M, n); 61 | outArea = find(psfLine<0.1); 62 | if isempty(outArea), 63 | error('Estimated PSF size exceeds the limit'); 64 | end 65 | IMGSIZE_REF = ceil(outArea(1)/(OSR*Nnum)); 66 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 67 | 68 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 69 | 70 | %%%%%%%%%%%%%% OTHER SIMULATION PARAMETERS %%%%%%%%%%%%%%%%%%%%%%% 71 | disp(['Size of PSF ~= ' num2str(IMGSIZE_REF) ' [microlens pitch]' ]); 72 | IMG_HALFWIDTH = max( Nnum*(IMGSIZE_REF + 1), 2*Nnum); 73 | disp(['Size of IMAGE = ' num2str(IMG_HALFWIDTH*2*OSR+1) 'X' num2str(IMG_HALFWIDTH*2*OSR+1) '' ]); 74 | x1space = (pixelPitch/OSR)*[-IMG_HALFWIDTH*OSR:1:IMG_HALFWIDTH*OSR]; 75 | x2space = (pixelPitch/OSR)*[-IMG_HALFWIDTH*OSR:1:IMG_HALFWIDTH*OSR]; 76 | x1length = length(x1space); 77 | x2length = length(x2space); 78 | 79 | x1MLspace = (pixelPitch/OSR)* [-(Nnum*OSR-1)/2 : 1 : (Nnum*OSR-1)/2]; 80 | x2MLspace = (pixelPitch/OSR)* [-(Nnum*OSR-1)/2 : 1 : (Nnum*OSR-1)/2]; 81 | x1MLdist = length(x1MLspace); 82 | x2MLdist = length(x2MLspace); 83 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 84 | 85 | %%%%%%%%%%%%%%%%%% FIND NON-ZERO POINTS %%%%%%%%%%%%%%%%%%%%%%%%%% 86 | validpts = find(objspace>eqtol); 87 | numpts = length(validpts); 88 | [p1indALL p2indALL p3indALL] = ind2sub( size(objspace), validpts); 89 | p1ALL = x1objspace(p1indALL)'; 90 | p2ALL = x2objspace(p2indALL)'; 91 | p3ALL = x3objspace(p3indALL)'; 92 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 93 | 94 | %%%%%%%%%%%%%%%%%%%%%%%% DEFINE ML ARRAY %%%%%%%%%%%%%%%%%%%%%%%%% 95 | MLARRAY = calcML(fml, k0, x1MLspace, x2MLspace, x1space, x2space); 96 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 97 | 98 | %%%%%%%%%%%%%%%%%%%%%% Alocate Memory for storing PSFs %%%%%%%%%%% 99 | LFpsfWAVE_STACK = zeros(x1length, x2length, numpts); 100 | psfWAVE_STACK = zeros(x1length, x2length, numpts); 101 | disp(['Start Calculating PSF...']); 102 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 103 | 104 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 105 | %%%%%%% PROJECTION FROM SINGLE POINT %%%%%%%%%%%%%%%%%%%%%%%%%%%%% 106 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 107 | centerPT = ceil(length(x1space)/2); 108 | halfWidth = Nnum*(IMGSIZE_REF + 0 )*OSR; 109 | centerArea = ( max((centerPT - halfWidth),1) : min((centerPT + halfWidth),length(x1space)) ); 110 | 111 | disp(['Computing PSFs (1/3)']); 112 | for eachpt=1:numpts, 113 | p1 = p1ALL(eachpt); 114 | p2 = p2ALL(eachpt); 115 | p3 = p3ALL(eachpt); 116 | 117 | IMGSIZE_REF_IL = ceil(IMGSIZE_REF*( abs(p3)/p3max)); 118 | halfWidth_IL = max(Nnum*(IMGSIZE_REF_IL + 0 )*OSR, 2*Nnum*OSR); 119 | centerArea_IL = ( max((centerPT - halfWidth_IL),1) : min((centerPT + halfWidth_IL),length(x1space)) ); 120 | disp(['size of center area = ' num2str(length(centerArea_IL)) 'X' num2str(length(centerArea_IL)) ]); 121 | 122 | %% excute PSF computing function 123 | [psfWAVE LFpsfWAVE] = calcPSF(p1, p2, p3, fobj, NA, x1space, x2space, pixelPitch/OSR, lambda, MLARRAY, fml, M, n, centerArea_IL); 124 | psfWAVE_STACK(:,:,eachpt) = psfWAVE; 125 | LFpsfWAVE_STACK(:,:,eachpt)= LFpsfWAVE; 126 | 127 | end 128 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 129 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 130 | 131 | 132 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 133 | %%%%%%%%%%%%% Compute Light Field PSFs (light field) %%%%%%%%%%%%% 134 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 135 | x1objspace = (pixelPitch/M)*[-floor(Nnum/2):1:floor(Nnum/2)]; 136 | x2objspace = (pixelPitch/M)*[-floor(Nnum/2):1:floor(Nnum/2)]; 137 | XREF = ceil(length(x1objspace)/2); 138 | YREF = ceil(length(x1objspace)/2); 139 | CP = ( (centerPT-1)/OSR+1 - halfWidth/OSR :1: (centerPT-1)/OSR+1 + halfWidth/OSR ); 140 | H = zeros( length(CP), length(CP), length(x1objspace), length(x2objspace), length(x3objspace) ); 141 | 142 | disp(['Computing LF PSFs (2/3)']); 143 | for i=1:length(x1objspace)*length(x2objspace)*length(x3objspace) , 144 | [a, b, c] = ind2sub([length(x1objspace) length(x2objspace) length(x3objspace)], i); 145 | psfREF = psfWAVE_STACK(:,:,c); 146 | 147 | psfSHIFT= im_shift2(psfREF, OSR*(a-XREF), OSR*(b-YREF) ); 148 | [f1,dx1,x1]=fresnel2D(psfSHIFT.*MLARRAY, pixelPitch/OSR, fml,lambda); 149 | f1= im_shift2(f1, -OSR*(a-XREF), -OSR*(b-YREF) ); 150 | 151 | xmin = max( centerPT - halfWidth, 1); 152 | xmax = min( centerPT + halfWidth, size(f1,1) ); 153 | ymin = max( centerPT - halfWidth, 1); 154 | ymax = min( centerPT + halfWidth, size(f1,2) ); 155 | 156 | f1_AP = zeros(size(f1)); 157 | f1_AP( (xmin:xmax), (ymin:ymax) ) = f1( (xmin:xmax), (ymin:ymax) ); 158 | [f1_AP_resize, x1shift, x2shift] = pixelBinning(abs(f1_AP.^2), OSR); 159 | f1_CP = f1_AP_resize( CP - x1shift, CP-x2shift ); 160 | 161 | H(:,:,a,b,c) = f1_CP; 162 | 163 | end 164 | 165 | for aa=1:size(H,3) 166 | for bb=1:size(H,4) 167 | for kk=1:size(H,5) 168 | temp=H(:,:,aa,bb,kk); 169 | H(:,:,aa,bb,kk)= H(:,:,aa,bb,kk)./sum(temp(:)); 170 | end 171 | end 172 | end 173 | 174 | x1space = (pixelPitch/1)*[-IMG_HALFWIDTH*1:1:IMG_HALFWIDTH*1]; 175 | x2space = (pixelPitch/1)*[-IMG_HALFWIDTH*1:1:IMG_HALFWIDTH*1]; 176 | x1space = x1space(CP); 177 | x2space = x2space(CP); 178 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 179 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 180 | 181 | 182 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 183 | %%%%%%%%%%%% Clear variables that are no longer necessary %%%%%%%% 184 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 185 | clear LFpsfWAVE_STACK; 186 | clear LFpsfWAVE_VIEW; 187 | clear psfWAVE_VIEW; 188 | clear LFpsfWAVE; 189 | clear PSF_AP; 190 | clear PSF_AP_resize; 191 | clear PSF_CP; 192 | clear f1; 193 | clear f1_AP; 194 | clear f1_AP_resize; 195 | clear f1_CP; 196 | clear psfREF; 197 | clear psfSHIFT; 198 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 199 | 200 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 201 | tol = 0.005; 202 | for i=1:size(H,5), 203 | H4Dslice = H(:,:,:,:,i); 204 | H4Dslice(find(H4Dslice< (tol*max(H4Dslice(:))) )) = 0; 205 | H(:,:,:,:,i) = H4Dslice; 206 | end 207 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 208 | 209 | 210 | 211 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 212 | %%%%%%%%%%%%%%%%% Estimate PSF size again %%%%%%%%%%%%%%%%%%%%%%% 213 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 214 | centerCP = ceil(length(CP)/2); 215 | CAindex = zeros(length(x3objspace),2); 216 | for i=1:length(x3objspace), 217 | IMGSIZE_REF_IL = ceil(IMGSIZE_REF*( abs(x3objspace(i))/p3max)); 218 | halfWidth_IL = max(Nnum*(IMGSIZE_REF_IL + 0 ), 2*Nnum); 219 | CAindex(i,1) = max( centerCP - halfWidth_IL , 1); 220 | CAindex(i,2) = min( centerCP + halfWidth_IL , size(H,1)); 221 | end 222 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 223 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 224 | 225 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 226 | %%%%%%%%%%%%%%%% Convert to phase-space PSF %%%%%%%%%%%%%%%%%%%%% 227 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 228 | IMGsize=size(H,1)-mod((size(H,1)-Nnum),2*Nnum); 229 | ideal_psf=zeros(IMGsize,IMGsize,Nnum,Nnum); %% phase-space PSF 230 | sLF=zeros(IMGsize,IMGsize,Nnum,Nnum); %% scanning light field images 231 | index1=round(size(H,1)/2)-fix(size(sLF,1)/2); 232 | index2=round(size(H,1)/2)+fix(size(sLF,1)/2); 233 | for ii=1:size(H,3) 234 | for jj=1:size(H,4) 235 | sLF(:,:,ii,jj)=im_shift3(squeeze(H(index1:index2,index1:index2,ii,jj)),ii-((Nnum+1)/2), jj-(Nnum+1)/2); 236 | end 237 | end 238 | 239 | multiWDF=zeros(Nnum,Nnum,size(sLF,1)/size(H,3),size(sLF,2)/size(H,4),Nnum,Nnum); %% multiplexed phase-space 240 | for i=1:size(H,3) 241 | for j=1:size(H,4) 242 | for a=1:size(sLF,1)/size(H,3) 243 | for b=1:size(sLF,2)/size(H,4) 244 | multiWDF(i,j,a,b,:,:)=squeeze( sLF( (a-1)*Nnum+i,(b-1)*Nnum+j,:,: ) ); 245 | end 246 | end 247 | end 248 | end 249 | WDF=zeros( size(sLF,1),size(sLF,2),Nnum,Nnum ); %% multiplexed phase-space 250 | for a=1:size(sLF,1)/size(H,3) 251 | for c=1:Nnum 252 | x=Nnum*a+1-c; 253 | for b=1:size(sLF,2)/size(H,4) 254 | for d=1:Nnum 255 | y=Nnum*b+1-d; 256 | WDF(x,y,:,:)=squeeze(multiWDF(:,:,a,b,c,d)); 257 | end 258 | end 259 | end 260 | end 261 | ideal_psf=WDF; 262 | ideal_psf=single(ideal_psf); 263 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 264 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 265 | 266 | 267 | %%%%%%%%%%%%% Estimate aberration with DAO %%%%%%%%%%%%%%%%%%%%%% 268 | load('Experimental_psf_M63_NA1.4_z1.mat','experimental_psf'); 269 | zern_index = estimate_aberration(ideal_psf,experimental_psf,Nnum); 270 | 271 | %%%%%%%%%%%%% Generate calibrated PSF %%%%%%%%%%%%%%%%%%%%%%%%%%%% 272 | %%%%%%%%%%%%% DEFINE OBJECT SPACE %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 273 | if mod(Nnum,2)==0, 274 | error(['Nnum should be an odd number']); 275 | end 276 | pixelPitch = MLPitch/Nnum; %% pitch of virtual pixels 277 | 278 | x1objspace = [0]; 279 | x2objspace = [0]; 280 | x3objspace = [zmin:zspacing:zmax]+1e-9; % offset 281 | objspace = ones(length(x1objspace),length(x2objspace),length(x3objspace)); 282 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 283 | 284 | 285 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 286 | p3max = max(abs(x3objspace)); 287 | x1testspace = (pixelPitch/OSR)* [0:1: Nnum*OSR*60]; 288 | x2testspace = [0]; 289 | [psfLine] = calcPSFFT(p3max, fobj, NA, x1testspace, pixelPitch/OSR, lambda, fml, M, n); 290 | outArea = find(psfLine<0.1); 291 | if isempty(outArea), 292 | error('Estimated PSF size exceeds the limit'); 293 | end 294 | IMGSIZE_REF = ceil(outArea(1)/(OSR*Nnum)); 295 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 296 | HALF_ML_NUM=IMGSIZE_REF; 297 | pixelPitch_OSR = MLPitch/OSR/Nnum; %simulated pixel size after OSR 298 | fov=length(-(HALF_ML_NUM+1)*OSR*Nnum:(HALF_ML_NUM+1)*OSR*Nnum)*pixelPitch_OSR; %the size of field of view for the PSF 299 | 300 | 301 | sinalpha_max = NA / n / M; 302 | fx_sinalpha = 1/(2*pixelPitch_OSR); 303 | fx_step = 1/fov ; 304 | fx_max = fx_sinalpha ; 305 | fx= -fx_max+fx_step/2 : fx_step : fx_max; 306 | [fxcoor fycoor] = meshgrid( fx , fx ); 307 | fx2coor=fxcoor.*fxcoor; 308 | fy2coor=fycoor.*fycoor; 309 | aperture_mask=((fx2coor+fy2coor)<=((NA/(lambda*M)).^2)); 310 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 311 | 312 | %%%%%%%%%%%%%% OTHER SIMULATION PARAMETERS %%%%%%%%%%%%%%%%%%%%%%% 313 | disp(['Size of PSF ~= ' num2str(IMGSIZE_REF) ' [microlens pitch]' ]); 314 | IMG_HALFWIDTH = max( Nnum*(IMGSIZE_REF + 1), 2*Nnum); 315 | disp(['Size of IMAGE = ' num2str(IMG_HALFWIDTH*2*OSR+1) 'X' num2str(IMG_HALFWIDTH*2*OSR+1) '' ]); 316 | x1space = (pixelPitch/OSR)*[-IMG_HALFWIDTH*OSR:1:IMG_HALFWIDTH*OSR]; 317 | x2space = (pixelPitch/OSR)*[-IMG_HALFWIDTH*OSR:1:IMG_HALFWIDTH*OSR]; 318 | x1length = length(x1space); 319 | x2length = length(x2space); 320 | 321 | x1MLspace = (pixelPitch/OSR)* [-(Nnum*OSR-1)/2 : 1 : (Nnum*OSR-1)/2]; 322 | x2MLspace = (pixelPitch/OSR)* [-(Nnum*OSR-1)/2 : 1 : (Nnum*OSR-1)/2]; 323 | x1MLdist = length(x1MLspace); 324 | x2MLdist = length(x2MLspace); 325 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 326 | 327 | %%%%%%%%%%%%%%%%%% FIND NON-ZERO POINTS %%%%%%%%%%%%%%%%%%%%%%%%%% 328 | validpts = find(objspace>eqtol); 329 | numpts = length(validpts); 330 | [p1indALL p2indALL p3indALL] = ind2sub( size(objspace), validpts); 331 | p1ALL = x1objspace(p1indALL)'; 332 | p2ALL = x2objspace(p2indALL)'; 333 | p3ALL = x3objspace(p3indALL)'; 334 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 335 | 336 | %%%%%%%%%%%%%%%%%%%%%%%% DEFINE ML ARRAY %%%%%%%%%%%%%%%%%%%%%%%%% 337 | MLARRAY = calcML(fml, k0, x1MLspace, x2MLspace, x1space, x2space); 338 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 339 | 340 | %%%%%%%%%%%%%%%%%%%%%% Alocate Memory for storing PSFs %%%%%%%%%%% 341 | LFpsfWAVE_STACK = zeros(x1length, x2length, numpts); 342 | psfWAVE_STACK = zeros(x1length, x2length, numpts); 343 | disp(['Start Calculating PSF...']); 344 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 345 | 346 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 347 | %%%%%%% PROJECTION FROM SINGLE POINT %%%%%%%%%%%%%%%%%%%%%%%%%%%%% 348 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 349 | centerPT = ceil(length(x1space)/2); 350 | halfWidth = Nnum*(IMGSIZE_REF + 0 )*OSR; 351 | centerArea = ( max((centerPT - halfWidth),1) : min((centerPT + halfWidth),length(x1space)) ); 352 | 353 | disp(['Computing PSFs (1/3)']); 354 | for eachpt=1:numpts, 355 | p1 = p1ALL(eachpt); 356 | p2 = p2ALL(eachpt); 357 | p3 = p3ALL(eachpt); 358 | 359 | IMGSIZE_REF_IL = ceil(IMGSIZE_REF*( abs(p3)/p3max)); 360 | halfWidth_IL = max(Nnum*(IMGSIZE_REF_IL + 0 )*OSR, 2*Nnum*OSR); 361 | centerArea_IL = ( max((centerPT - halfWidth_IL),1) : min((centerPT + halfWidth_IL),length(x1space)) ); 362 | disp(['size of center area = ' num2str(length(centerArea_IL)) 'X' num2str(length(centerArea_IL)) ]); 363 | 364 | %% excute PSF computing funcion 365 | [psfWAVE LFpsfWAVE] = calcPSF(p1, p2, p3, fobj, NA, x1space, x2space, pixelPitch/OSR, lambda, MLARRAY, fml, M, n, centerArea_IL); 366 | data=zeros(2,round(NA/(lambda*M)/fx_step*2+1)); 367 | data(1,:)=linspace(-1,1,size(data,2)); 368 | data(2,:)=linspace(-1,1,size(data,2)); 369 | aber_phase=SH(zern_index,data); 370 | aber_phase2=padarray( aber_phase,[(size(aperture_mask,1)-size(aber_phase,1))/2,(size(aperture_mask,2)-size(aber_phase,2))/2] ); 371 | 372 | psfWAVE_STACK(:,:,eachpt) = ifft2(ifftshift(fftshift(fft2(psfWAVE)).*exp(1j.*aber_phase2))); 373 | LFpsfWAVE_STACK(:,:,eachpt)= LFpsfWAVE; 374 | 375 | end 376 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 377 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 378 | 379 | 380 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 381 | %%%%%%%%%%%%% Compute Light Field PSFs (light field) %%%%%%%%%%%%% 382 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 383 | x1objspace = (pixelPitch/M)*[-floor(Nnum/2):1:floor(Nnum/2)]; 384 | x2objspace = (pixelPitch/M)*[-floor(Nnum/2):1:floor(Nnum/2)]; 385 | XREF = ceil(length(x1objspace)/2); 386 | YREF = ceil(length(x1objspace)/2); 387 | CP = ( (centerPT-1)/OSR+1 - halfWidth/OSR :1: (centerPT-1)/OSR+1 + halfWidth/OSR ); 388 | H = zeros( length(CP), length(CP), length(x1objspace), length(x2objspace), length(x3objspace) ); 389 | 390 | disp(['Computing LF PSFs (2/3)']); 391 | for i=1:length(x1objspace)*length(x2objspace)*length(x3objspace) , 392 | [a, b, c] = ind2sub([length(x1objspace) length(x2objspace) length(x3objspace)], i); 393 | psfREF = psfWAVE_STACK(:,:,c); 394 | 395 | psfSHIFT= im_shift2(psfREF, OSR*(a-XREF), OSR*(b-YREF) ); 396 | [f1,dx1,x1]=fresnel2D(psfSHIFT.*MLARRAY, pixelPitch/OSR, fml,lambda); 397 | f1= im_shift2(f1, -OSR*(a-XREF), -OSR*(b-YREF) ); 398 | 399 | xmin = max( centerPT - halfWidth, 1); 400 | xmax = min( centerPT + halfWidth, size(f1,1) ); 401 | ymin = max( centerPT - halfWidth, 1); 402 | ymax = min( centerPT + halfWidth, size(f1,2) ); 403 | 404 | f1_AP = zeros(size(f1)); 405 | f1_AP( (xmin:xmax), (ymin:ymax) ) = f1( (xmin:xmax), (ymin:ymax) ); 406 | [f1_AP_resize, x1shift, x2shift] = pixelBinning(abs(f1_AP.^2), OSR); 407 | f1_CP = f1_AP_resize( CP - x1shift, CP-x2shift ); 408 | 409 | H(:,:,a,b,c) = f1_CP; 410 | 411 | end 412 | 413 | for aa=1:size(H,3) 414 | for bb=1:size(H,4) 415 | for kk=1:size(H,5) 416 | temp=H(:,:,aa,bb,kk); 417 | H(:,:,aa,bb,kk)= H(:,:,aa,bb,kk)./sum(temp(:)); 418 | end 419 | end 420 | end 421 | 422 | x1space = (pixelPitch/1)*[-IMG_HALFWIDTH*1:1:IMG_HALFWIDTH*1]; 423 | x2space = (pixelPitch/1)*[-IMG_HALFWIDTH*1:1:IMG_HALFWIDTH*1]; 424 | x1space = x1space(CP); 425 | x2space = x2space(CP); 426 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 427 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 428 | 429 | 430 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 431 | %%%%%%%%%%%% Clear variables that are no longer necessary %%%%%%%% 432 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 433 | clear LFpsfWAVE_STACK; 434 | clear LFpsfWAVE_VIEW; 435 | clear psfWAVE_VIEW; 436 | clear LFpsfWAVE; 437 | clear PSF_AP; 438 | clear PSF_AP_resize; 439 | clear PSF_CP; 440 | clear f1; 441 | clear f1_AP; 442 | clear f1_AP_resize; 443 | clear f1_CP; 444 | clear psfREF; 445 | clear psfSHIFT; 446 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 447 | 448 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 449 | tol = 0.005; 450 | for i=1:size(H,5), 451 | H4Dslice = H(:,:,:,:,i); 452 | H4Dslice(find(H4Dslice< (tol*max(H4Dslice(:))) )) = 0; 453 | H(:,:,:,:,i) = H4Dslice; 454 | end 455 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 456 | 457 | 458 | 459 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 460 | %%%%%%%%%%%%%%%%% Estimate PSF size again %%%%%%%%%%%%%%%%%%%%%%% 461 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 462 | centerCP = ceil(length(CP)/2); 463 | CAindex = zeros(length(x3objspace),2); 464 | for i=1:length(x3objspace), 465 | IMGSIZE_REF_IL = ceil(IMGSIZE_REF*( abs(x3objspace(i))/p3max)); 466 | halfWidth_IL = max(Nnum*(IMGSIZE_REF_IL + 0 ), 2*Nnum); 467 | CAindex(i,1) = max( centerCP - halfWidth_IL , 1); 468 | CAindex(i,2) = min( centerCP + halfWidth_IL , size(H,1)); 469 | end 470 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 471 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 472 | 473 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 474 | %%%%%%%%%%%%%%%% Convert to phase-space PSF %%%%%%%%%%%%%%%%%%%%% 475 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 476 | IMGsize=size(H,1)-mod((size(H,1)-Nnum),2*Nnum); 477 | psf=zeros(IMGsize,IMGsize,Nnum,Nnum,size(H,5)); %% phase-space PSF 478 | for z=1:size(H,5) 479 | 480 | sLF=zeros(IMGsize,IMGsize,Nnum,Nnum); %% scanning light field images 481 | index1=round(size(H,1)/2)-fix(size(sLF,1)/2); 482 | index2=round(size(H,1)/2)+fix(size(sLF,1)/2); 483 | for ii=1:size(H,3) 484 | for jj=1:size(H,4) 485 | sLF(:,:,ii,jj)=im_shift3(squeeze(H(index1:index2,index1:index2,ii,jj,z)),ii-((Nnum+1)/2), jj-(Nnum+1)/2); 486 | end 487 | end 488 | 489 | multiWDF=zeros(Nnum,Nnum,size(sLF,1)/size(H,3),size(sLF,2)/size(H,4),Nnum,Nnum); %% multiplexed phase-space 490 | for i=1:size(H,3) 491 | for j=1:size(H,4) 492 | for a=1:size(sLF,1)/size(H,3) 493 | for b=1:size(sLF,2)/size(H,4) 494 | multiWDF(i,j,a,b,:,:)=squeeze( sLF( (a-1)*Nnum+i,(b-1)*Nnum+j,:,: ) ); 495 | end 496 | end 497 | end 498 | end 499 | WDF=zeros( size(sLF,1),size(sLF,2),Nnum,Nnum ); %% multiplexed phase-space 500 | for a=1:size(sLF,1)/size(H,3) 501 | for c=1:Nnum 502 | x=Nnum*a+1-c; 503 | for b=1:size(sLF,2)/size(H,4) 504 | for d=1:Nnum 505 | y=Nnum*b+1-d; 506 | WDF(x,y,:,:)=squeeze(multiWDF(:,:,a,b,c,d)); 507 | end 508 | end 509 | end 510 | end 511 | psf(:,:,:,:,z)=WDF; 512 | 513 | end 514 | psf=single(psf); 515 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 516 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 517 | 518 | 519 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 520 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 521 | disp(['Saving PSF matrix file...']); 522 | save(['../PSF/Calibrated_psf_M',num2str(M),'_NA',num2str(NA),'_zmin',num2str(zmin*1e+6),'u_zmax',num2str(zmax*1e+6),'u.mat'],'psf','-v7.3'); 523 | disp(['PSF computation complete.']); 524 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 525 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 526 | 527 | 528 | 529 | 530 | -------------------------------------------------------------------------------- /NI_codes/proj/NIController.lvproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | true 6 | false 7 | 0 8 | My Computer/VI Server 9 | My Computer/VI Server 10 | true 11 | true 12 | false 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | true 167 | 168 | 169 | 170 | 171 | true 172 | {0518FF3F-B7A0-46AD-89EF-55E702291CC2} 173 | {B7DAD71B-5CE9-487D-B9B9-CCE1FC76F2C4} 174 | 8002 175 | true 176 | {5290F2B0-B175-45AE-9523-505CDD81EDE4} 177 | FinalDll 178 | true 179 | true 180 | true 181 | ../builds/scanProj/NIConrtolVersion2 182 | relativeToCommon 183 | true 184 | {495918CE-82C4-4699-90FA-DABCCED1C399} 185 | 13 186 | 1 187 | NIControl.dll 188 | ../builds/scanProj/NIConrtolVersion2/NIControl.dll 189 | true 190 | App 191 | Support Directory 192 | ../builds/scanProj/NIConrtolVersion2/data 193 | 2 194 | false 195 | true 196 | {8250BAB0-5DFF-4A46-A867-4145BE00F992} 197 | {6CA30F21-7151-4660-9290-A3827C40E892} 198 | true 199 | {78BC1C35-8BF6-4832-93FE-4C713D32ED0B} 200 | Container 201 | 0 202 | 1 203 | -1 204 | -1 205 | -1 206 | return value 207 | -1 208 | 0 209 | 0 210 | 24 211 | -1 212 | -1 213 | start 214 | -1 215 | 1 216 | 0 217 | 22 218 | -1 219 | -1 220 | XShiftRatio 221 | -1 222 | 1 223 | 0 224 | 23 225 | -1 226 | -1 227 | YShiftRatio 228 | -1 229 | 1 230 | 0 231 | 18 232 | -1 233 | -1 234 | VXPX 235 | -1 236 | 1 237 | 0 238 | 19 239 | -1 240 | -1 241 | VYPY 242 | -1 243 | 1 244 | 0 245 | 15 246 | -1 247 | -1 248 | VoltageScanningChannel 249 | -1 250 | 1 251 | 0 252 | 16 253 | -1 254 | -1 255 | LaserTriggerChannel 256 | -1 257 | 1 258 | 0 259 | 17 260 | -1 261 | -1 262 | frequency 263 | -1 264 | 1 265 | 0 266 | 20 267 | -1 268 | -1 269 | z_num 270 | -1 271 | 1 272 | 0 273 | 21 274 | -1 275 | -1 276 | delta_zX1um 277 | -1 278 | 1 279 | 0 280 | 3 281 | -1 282 | -1 283 | Mode 284 | -1 285 | 1 286 | 0 287 | 0 288 | -1 289 | -1 290 | laser1 291 | -1 292 | 1 293 | 0 294 | 13 295 | -1 296 | -1 297 | LoopDelaySecond 298 | -1 299 | 1 300 | 0 301 | 12 302 | -1 303 | -1 304 | TriggerDelayMs 305 | -1 306 | 1 307 | 0 308 | 25 309 | -1 310 | -1 311 | RotationAlpha 312 | -1 313 | 1 314 | 0 315 | 27 316 | -1 317 | -1 318 | RotationBeta 319 | -1 320 | 1 321 | 0 322 | 10 323 | -1 324 | -1 325 | ExposureTimeMs 326 | -1 327 | 1 328 | 0 329 | 2 330 | -1 331 | -1 332 | User1_float 333 | -1 334 | 1 335 | 1 336 | Kx_4_ZScanning 337 | 0 338 | 6 339 | -1 340 | -1 341 | User2_int 342 | -1 343 | 1 344 | 0 345 | 1 346 | -1 347 | -1 348 | laser2 349 | -1 350 | 1 351 | 0 352 | 4 353 | -1 354 | -1 355 | laser3 356 | -1 357 | 1 358 | 0 359 | 5 360 | -1 361 | -1 362 | laser4 363 | -1 364 | 1 365 | 0 366 | 7 367 | -1 368 | -1 369 | k 370 | -1 371 | 1 372 | 0 373 | 8 374 | -1 375 | -1 376 | IfScanning 377 | -1 378 | 1 379 | 0 380 | 9 381 | -1 382 | -1 383 | DCOffsetX 384 | -1 385 | 1 386 | 0 387 | 14 388 | -1 389 | -1 390 | DCOffsetY 391 | -1 392 | 1 393 | '1#!!!!!!"Q!$5!$!!:M98.F=D%!!!V!!Q!'<'&T:8)S!!!:1!I!%AI+#AI+#AJ6=W6S-6^G<'^B>!!!#U!$!!2.<W2F!!!.1!-!"GRB=W6S-Q!!$5!$!!:M98.F=D1!!!^!!Q!*68.F=D*@;7ZU!!>!!Q!";Q!21!I!#UFG)&.D97ZO;7ZH!"&!#A!,2%-A4W:G=W6U)&A!&U!+!""&?("P=X6S:62J<75I<8-J!!!%!!!!&U!+!""5=GFH:W6S2'6M98EI<8-J!!!81!I!%5RP<X"%:7RB?3BT:7.P<G1J!"&!#A!,2%-A4W:G=W6U)&E!.E!X`````Q!/'1#!!!!!!!%!"!!!!!%!!!!!!!!76G^M>'&H:6.D97ZO;7ZH1WBB<GZF<!!!-E!X`````Q!/'1#!!!!!!!%!"!!!!!%!!!!!!!!44'&T:8*5=GFH:W6S1WBB<GZF<!!01!I!#7:S:8&V:7ZD?1!,1!I!"&:95&A!!!N!#A!%6FF171!!#U!+!!6[8WZV<1!41!I!$72F<(2B8XII?$&V<3E!%5!+!!N95WBJ:H23982J<Q!21!I!#VF4;'FG>&*B>'FP!!J!)14.I^;Z!!!41!I!$6*P>'&U;7^O17RQ;'%!%U!+!!R3<X2B>'FP<E*F>'%!!,1!]!!=!!!!!1!#!!-!"!!&!!9!"Q!)!!E!#A!,!!Q!$1!/!!]!%!!2!")!%Q!5!"5!&A!8!"A!'1!,!"I$!!%9!!!+!!!!#!!!!!A!!!!)!!!!#A!!!!A!!!!)!!!!#!!!!!A!!!!)!!!!#A!!!!!!!!!+!!!!#!!!!!A!!!%+!!!"#A!!!!A!!!!+!!!!#A!!!!I!!!!+!!!!#A!!!!I!!!!+!!!!#A!!!!!!!!!+!!!!!!%!'Q 394 | 27 395 | /My Computer/Final.vi 396 | TopLevel 397 | ExportedVI 398 | 0 399 | 1 400 | -1 401 | -1 402 | -1 403 | return value 404 | -1 405 | 0 406 | 1 407 | SetStop 408 | 0 409 | 7 410 | -1 411 | -1 412 | stop 413 | -1 414 | 1 415 | '1#!!!!!!!-!"!!!!!V!!Q!(4H6N:8*J9Q"5!0!!$!!!!!!!!!!!!!!!!!!!!!%!!!!!!!!!!!)!!(A!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!)!!!!!!!!!!!!!!!!!!!!!!!!!!!"!!) 416 | 2 417 | /My Computer/SetGlobal.vi 418 | TopLevel 419 | ExportedVI 420 | 3 421 | FinalDll 422 | FinalDll 423 | Copyright ?2019 424 | FinalDll 425 | {AFF086CD-FA83-4689-9921-BBA3537128DF} 426 | NIControl.dll 427 | true 428 | 429 | 430 | 431 | 432 | --------------------------------------------------------------------------------