initial commit

This commit is contained in:
2026-08-07 15:56:42 +09:00
commit 91ad25aca9
1012 changed files with 159314 additions and 0 deletions
@@ -0,0 +1,216 @@
% ADD_MOMENTUM_OBJECT speed up convergence by adding momentum / integral term into the
% update direction for the MLc method
%
% [self, cache] = add_momentum_object(self, cache, par, object_upd_sum, iter, fourier_error)
%
% ** self structure containing inputs: e.g. current reconstruction results, data, mask, positions, pixel size, ..
% ** cache structure with precalculated values to avoid unnecessary overhead
% ** par structure containing parameters for the engines
% ** object_upd_sum cell of arrays containing update direction from the LSQML method
% ** iter current iteation numebr
% ** fourier_error array [Npos,1] containing evolution of reconstruction error
%
% returns:
% ++ self structure containing inputs: e.g. current reconstruction results, data, mask, positions, pixel size, ..
% ++ cache structure with precalculated values to avoid unnecessary overhead
%
%
% Academic License Agreement
%
% Source Code
%
% Introduction
% This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
% will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
% ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
%
% Terms and Conditions of the LICENSE
% 1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
% hereinafter set out and until termination of this license as set forth below.
% 2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
% or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
% LICENSEEs responsibility to ensure its proper use and the correctness of the results.
% 3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
% A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
% HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
% OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
% 4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
% "IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
% license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
% profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
% in the commercial use, application or exploitation of works similar to the PROGRAM.
% 5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
% another computing language:
% "Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
% Scherrer Institut, Switzerland."
%
% Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
% P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379382 (2008).
% (doi: 10.1126/science.1158573),
% for mixed coherent modes:
% P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 6871 (2013). (doi: 10.1038/nature11806),
% for LSQ-ML method
% M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
% for OPRP method
% M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
% and/or for multislice:
% E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 2908929108 (2016).
% 6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
% names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
% 7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
% agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
% make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
% © All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
% 8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
% 9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
% to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
% in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
% in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
% 10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
% the courts of Zürich, Switzerland.
function [self, cache] = add_momentum_object(self, cache, par, object_upd_sum, iter, fourier_error, beta_object)
import utils.*
import engines.GPU_MS.GPU_wrapper.*
import math.*
verbose(1, 'Adding momentum to object')
object_modes = size(self.object,1);
% create velocity maps in the first iterations
if iter == par.object_change_start
cache.object_upd_sum = cell(object_modes,1);
for ll = 1:object_modes
for jj = 1:par.Nlayers
cache.velocity_map_object{ll,jj} = Gzeros(self.Np_o);
cache.object_upd_sum{ll,jj} = [];
end
end
end
% store previous update directions
for ll = 1:object_modes
for jj = 1:par.Nlayers
upd = object_upd_sum{ll,jj}(cache.object_ROI{:})* mean(beta_object(:,jj));
upd = upd / norm2(upd);
cache.object_upd_sum{ll,jj} = [cache.object_upd_sum{ll,jj}, {upd}];
end
end
% how many steps are stored to calculate optimal friction
momentum_memory = 2;
% use Fourier error to avoid issues with convergence
ind_compare = find(all(~isnan(fourier_error),2),3,'last');
if length(ind_compare) > 2
merr = mean(fourier_error,2);
ferr_ok = max(merr(ind_compare([1,2]))) > min(merr(ind_compare([2,3])));
else
ferr_ok = true;
end
if iter > momentum_memory+par.object_change_start
for ll = 1:object_modes
for jj = 1:par.Nlayers
cache.object_upd_sum{ll,jj}(1) = []; % delete the oldest stored object update
corr_level = nan;
if ferr_ok
% caculate correlation between updated to estimate optimal
% friction, !! NOTE that cache.object_upd_sum contains only the
% object_ROI region !!
%
switch momentum_memory
case 2, [aux{1}, aux{2}] = compare_upd_directions_2(cache.object_upd_sum{ll,jj}{:});
case 3, [aux{1}, aux{2}, aux{3}] = compare_upd_directions_2(cache.object_upd_sum{ll,jj}{:});
othewise, error('Not implemented')
end
for kk = 1:momentum_memory
corr_level(kk) = real(Ggather(mean2(aux{kk})));
end
end
if ferr_ok && all(corr_level > 0 )
% estimate optimal friction from previous steps
poly_fit = polyfit(0:momentum_memory,[0,log(corr_level)],1);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
gain = par.momentum; % smaller -> lower relative speed (less momentum)
friction = 0.5*max(-poly_fit(1),0); % smaller -> longer memory, more momentum
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% update object by the momentum gradient
[self.object{ll,jj}, cache.velocity_map_object{ll,jj}] = update_momentum(self.object{ll,jj}, cache.velocity_map_object{ll,jj}, object_upd_sum{ll,jj}, friction, gain, cache.illum_sum_0{ll}, cache.MAX_ILLUM(ll));
else
% error was increased or updates are not well correlated, skip acceleration
gain = 0; friction = inf;
cache.velocity_map_object{ll,jj} = cache.velocity_map_object{ll,jj}/2;
end
if verbose()> 1
norm_upd = norm2(object_upd_sum{ll,jj});
norm_vmap = norm2(gain.*cache.velocity_map_object{ll,jj});
verbose(2,['Object %i Corr=', repmat('1:%5.2f ',1,momentum_memory)],ll, corr_level )
verbose(0, 'Momentum: friction=%3.1e \tacceleration %1.1fx',friction, 1+norm_vmap/norm_upd)
end
end
end
% plotting.smart_figure(25454)
% img = cat(1,cat(2, cache.velocity_map_object{:}) .* cat(2,cache.illum_sum_0{:}), cat(2, object_upd_sum{:}) .* cat(2,cache.illum_sum_0{:}));
% aimg = abs(img);
% img = min(aimg, quantile(aimg(:), 0.99)) .* img ./ (aimg+1e-3);
% plotting.imagesc3D(img(1:4:end, 1:4:end))
% axis off image xy
% drawnow
try
if verbose()> 2
plotting.smart_figure(121)
subplot(1,2,1)
plotting.imagesc3D(cache.velocity_map_object{1,1})
axis off image
title(sprintf('Velocity, iter=%i', iter))
subplot(1,2,2)
plotting.imagesc3D(object_upd_sum{1,1})
axis off image
title('Gradient')
drawnow
end
catch
keyboard
end
end
end
function [object, Vmap] = update_momentum(object, Vmap, Vmap_upd, friction, gain, weight, w_max)
% auxiliary function
weight = weight ./ (0.1*w_max+weight);
Vmap = (1-friction)*Vmap + Vmap_upd;
object = object + weight.*gain.*Vmap;
end
function [out1, out2] = compare_upd_directions_2(upd1, upd2, upd3)
% compare updates
upd3 = conj(upd3);
out2 = upd1 .* upd3;
out1 = upd2 .* upd3;
end
function [out1, out2, out3] = compare_upd_directions_3(upd1, upd2, upd3, upd4)
% compare updates
upd4 = conj(upd4);
out3 = upd1 .* upd4;
out2 = upd2 .* upd4;
out1 = upd3 .* upd4;
end
@@ -0,0 +1,197 @@
% ADD_MOMENTUM_PROBE speed up convergence by adding momentum / integral term into the
% update direction for the MLc method
%
% [self, cache] = add_momentum_probe(self, cache, par, probe_upd, iter, fourier_error)
%
% ** self structure containing inputs: e.g. current reconstruction results, data, mask, positions, pixel size, ..
% ** cache structure with precalculated values to avoid unnecessary overhead
% ** par structure containing parameters for the engines
% ** probe_upd cell of arrays containing update direction from the LSQML method
% ** iter current iteation numebr
% ** fourier_error array [Npos,1] containing evolution of reconstruction error
%
% returns:
% ++ self structure containing inputs: e.g. current reconstruction results, data, mask, positions, pixel size, ..
% ++ cache structure with precalculated values to avoid unnecessary overhead
%
%
% Academic License Agreement
%
% Source Code
%
% Introduction
% This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
% will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
% ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
%
% Terms and Conditions of the LICENSE
% 1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
% hereinafter set out and until termination of this license as set forth below.
% 2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
% or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
% LICENSEEs responsibility to ensure its proper use and the correctness of the results.
% 3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
% A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
% HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
% OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
% 4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
% "IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
% license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
% profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
% in the commercial use, application or exploitation of works similar to the PROGRAM.
% 5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
% another computing language:
% "Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
% Scherrer Institut, Switzerland."
%
% Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
% P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379382 (2008).
% (doi: 10.1126/science.1158573),
% for mixed coherent modes:
% P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 6871 (2013). (doi: 10.1038/nature11806),
% for LSQ-ML method
% M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
% for OPRP method
% M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
% and/or for multislice:
% E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 2908929108 (2016).
% 6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
% names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
% 7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
% agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
% make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
% © All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
% 8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
% 9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
% to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
% in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
% in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
% 10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
% the courts of Zürich, Switzerland.
function [self, cache] = add_momentum_probe(self, cache, par, probe_upd, iter, fourier_error, beta_probe)
import utils.*
import engines.GPU_MS.GPU_wrapper.*
import math.*
verbose(1, 'Adding momentum to probe')
Nmodes = size(self.probe,1);
% create velocity maps in the first iterations
if iter == par.probe_change_start
cache.probe_upd_sum = cell(Nmodes,1);
for ll = 1:Nmodes
cache.velocity_map_probe{ll} = Gzeros(self.Np_p);
cache.probe_upd_sum{ll} = [];
end
end
% store previous update directions
for ll = 1:Nmodes
probe_upd{ll} = probe_upd{ll}(:,:,:,1); % accelerate only the fundamental probe in the variable probe extension
probe_upd{ll} = probe_upd{ll} .* mean(beta_probe(:));
upd = probe_upd{ll} ./ (norm2(probe_upd{ll})+eps);
cache.probe_upd_sum{ll} = [cache.probe_upd_sum{ll}, {upd}];
end
% how many steps are stored to calculate optimal friction
momentum_memory = 3;
if iter > momentum_memory+par.probe_change_start
for ll = 1:Nmodes
probe_modes= size(self.probe{ll},3);
cache.probe_upd_sum{ll}(1) = []; % delete the oldest stored probe update
% caculate correlation between updated to estimate optimal
% friction,
[aux{1}, aux{2}, aux{3}] = compare_upd_directions(cache.probe_upd_sum{ll}{:});
for kk = 1:momentum_memory
corr_level(kk,:) = real(Ggather(mean2(aux{kk})));
end
% use Fourier error to avoid issues with convergence
ind_compare = find(all(~isnan(fourier_error),2),3,'last');
if length(ind_compare) > 2
merr = mean(fourier_error,2);
ferr_ok = max(merr(ind_compare([1,2]))) > min(merr(ind_compare([2,3])));
else
ferr_ok = true;
end
if all(corr_level(:) > 0 ) && ferr_ok
try
% estimate optimal friction from previous steps
poly_fit = polyfit(repmat(0:momentum_memory,probe_modes,1),[zeros(1,probe_modes);log(corr_level)]',1);
catch
keyboard
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
gain = par.momentum; % smaller -> lower relative speed (less momentum)
friction = 0.5*max(-poly_fit(1),0); % smaller -> longer memory, more momentum
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% update probe by the momentum gradient , accelerate only the fundamental probe in the variable probe extension
[self.probe{ll}(:,:,:,1), cache.velocity_map_probe{ll}] = update_momentum(self.probe{ll}(:,:,:,1), cache.velocity_map_probe{ll}, probe_upd{ll}, friction, gain);
else
% error was increased or updates are not well correlated, skip acceleration
gain = 0; friction = inf;
cache.velocity_map_probe{ll} = cache.velocity_map_probe{ll}/2;
end
if verbose() > 0
norm_upd = mean(norm2(probe_upd{ll}));
norm_vmap = eps+mean(norm2(gain.*cache.velocity_map_probe{ll}));
verbose(2,['Probe %i Corr=', repmat('1:%5.2f ',1,momentum_memory)],ll, corr_level(:,1) )
verbose(0, 'Momentum: friction=%3.1e \tacceleration %1.1fx',friction(:,1), 1+norm_vmap./norm_upd(1))
end
end
% plotting.smart_figure(25454)
% img = cat(1,cat(2, cache.velocity_map_probe{:}) .* cat(2,cache.illum_sum_0{:}), cat(2, probe_upd_sum{:}) .* cat(2,cache.illum_sum_0{:}));
% aimg = abs(img);
% img = min(aimg, quantile(aimg(:), 0.99)) .* img ./ (aimg+1e-3);
% plotting.imagesc3D(img(1:4:end, 1:4:end))
% axis off image xy
% drawnow
try
if verbose() > 2
plotting.smart_figure(1213)
subplot(1,2,1)
plotting.imagesc3D(cache.velocity_map_probe{1,1})
axis off image
title(sprintf('Velocity, iter=%i, norm=%g', iter, norm2(cache.velocity_map_probe{1,1})))
subplot(1,2,2)
plotting.imagesc3D(probe_upd{1})
axis off image
title(sprintf('Gradient, norm=%g',norm2(probe_upd{1})))
drawnow
end
catch
keyboard
end
end
end
function [probe, Vmap] = update_momentum(probe, Vmap, Vmap_upd, friction, gain)
% auxiliary function
Vmap = (1-friction)*Vmap + Vmap_upd;
probe = probe + gain.*Vmap;
end
function [out1, out2, out3] = compare_upd_directions(upd1, upd2, upd3, upd4)
% compare updates
upd4 = conj(upd4);
out3 = upd1 .* upd4;
out2 = upd2 .* upd4;
out1 = upd3 .* upd4;
end
@@ -0,0 +1,97 @@
% GET_FORWARD_MODEL from the provided object and probe calculate the exit wave
%
% [self, probe, obj_proj, psi] = get_forward_model(self, obj_proj, par, cache, g_ind, p_ind, scan_ids, layer_ids)
%
% ** self structure containing inputs: e.g. current reconstruction results, data, mask, positions, pixel size, ..
% ** obj_proj [Nx,Ny,N] array, just a preallocated array on GPU, can be empty
% ** par structure containing parameters for the engines
% ** cache structure with precalculated values to avoid unnecessary overhead
% ** g_ind indices corresponding to the current group that is solved in parallel
% ** p_ind indices containg corresponding probe id for each processed position
% ** scan_ids determines to which scan correponds each of the position
% ** layer_ids id of the solved layer for multilayer ptycho
%
%
% returns:
% ++ self structure containing inputs: e.g. current reconstruction results, data, mask, positions, pixel size, ..
% ++ probe either [Nx,Nx,1] or [Nx,Nx,N] aarray of shared probe or variable probe that differs for each position
% ++ obj_proj [Nx,Ny,N] array, views of the object for each scan position
% ++ psi [Nx,Ny,N] array, complex valued exit-wave (psi = P*O)
%
% see also: engines.GPU_MS.LSQML
function [self, probe, obj_proj, psi] = get_forward_model(self, obj_proj, par, cache, g_ind, p_ind, scan_ids, layer_ids)
import engines.GPU_MS.shared.*
import engines.GPU_MS.GPU_wrapper.*
import engines.GPU_MS.LSQML.*
import math.*
import utils.*
import plotting.*
if isempty(obj_proj{1})
for ll = 1:par.object_modes
obj_proj{ll} = Gzeros([self.Np_p, 0], true);
end
end
% allocate memory for probes. Added by ZC
% probe = self.probe;
if par.Nlayers > 1
probe=cell(par.probe_modes,par.Nlayers+1);
end
% get illumination probe
for ll = 1:par.probe_modes
if (ll == 1 && (par.variable_probe || par.variable_intensity))
% add variable probe (OPRP) part into the constant illumination
probe{ll,1} = get_variable_probe(self.probe{ll}, self.probe_evolution(g_ind,:),p_ind{ll});
else
% store the normal (constant) probe(s)
probe{ll,1} = self.probe{min(ll,end)}(:,:,min(end,p_ind{ll}),1);
end
if (ll == 1 && par.apply_subpix_shift && isinf(self.z_distance(end))) || is_used(par,'fly_scan')
% only in farfield mode
probe{ll,1} = apply_subpx_shift(probe{ll,1}, self.modes{min(end,ll)}.sub_px_shift(g_ind,:) );
end
if (ll == 1)
probe{ll,1} = apply_subpx_shift_fft(probe{ll,1}, self.modes{1}.probe_fourier_shift(g_ind,:));
end
end
% allocate memory for psi. Added by ZC
psi=cell(max(par.object_modes, par.probe_modes),1);
% get projection of the object and probe
for layer = 1:par.Nlayers
for ll = 1:max(par.object_modes, par.probe_modes)
llo = min(ll, par.object_modes);
llp = min(ll, par.probe_modes);
% get objects projections
obj_proj{llo} = get_views(self.object, obj_proj{llo},layer_ids(layer),llo, g_ind, cache, scan_ids,[]);
if (ll == 1 && par.apply_subpix_shift && ~isinf(self.z_distance(end)))
% only in nearfield mode , apply shift in the opposite direction
obj_proj{ll} = apply_subpx_shift(obj_proj{ll} .* cache.apodwin, -self.modes{min(end,ll)}.sub_px_shift(g_ind,:) ) ./ cache.apodwin;
end
% get exitwave after each layer
psi{ll} = probe{llp,layer} .* obj_proj{llo};
%modified by YJ: no need to do another propagation after the
%last object layer
if layer < par.Nlayers
% fourier propagation
[psi{ll}] = fwd_fourier_proj(psi{ll} , self.modes{layer}, g_ind);
if par.Nlayers > 1
probe{llp,layer+1} = psi{llp};
end
end
end
end
% At this point, psi is the exit wave after the last object layer
% Now propagate the wave function to far-field (detector) plane
% This is same as using fwd_fourier_proj w. distance = inf and no camera angle refinement
for ll= 1:max(par.object_modes, par.probe_modes)
psi{ll} = fft2_safe(psi{ll}); % fully farfield
end
end
@@ -0,0 +1,143 @@
% GET_OPTIMAL_LSQ_STEP calculate the optimal step lenght for given update directions and chi array
%
% [beta_probe, beta_object] = get_optimal_LSQ_step(self,chi,dO,dP,O,P, p_ind, par)
%
% ** self structure containing inputs: e.g. current reconstruction results, data, mask, positions, pixel size, ..
% ** chi [Nx,Ny,N] array, difference between original and updated exit-wave
% ** dO [Nx,Ny,N] array, object update direction
% ** dP [Nx,Ny,N] array, probe update direction
% ** O [Nx,Ny,N] array, object views
% ** P [Nx,Ny,1] or [Nx,Ny,N] array, single or variable probe
% ** p_ind indices containg corresponding probe id for each processed position
% ** par structure containing parameters for the engines
%
% returns:
% ++ beta_probe optimal probe step
% ++ beta_object optimal object step
%
% see also: engines.GPU_MS.LSQML
function [beta_probe, beta_object] = get_optimal_LSQ_step(self,chi,dO,dP,O,P, p_ind, par)
% find optimal step in the LSQ sense
import engines.GPU_MS.GPU_wrapper.*
import math.*
global gpu use_gpu
if ~isempty(gpu); wait(gpu); end
grouping = size(chi,3);
lambda_0 = eps(single(1)) / prod(self.Np_p);
lambda_LSQ = 0.1; % add some small regularization to avoid instabilities
if use_gpu
% fast mex based CUDA version
if size(dP,3) == grouping
p_ind = 1:grouping; % one update for each position
elseif size(dP,3) == 1 && numel(p_ind) == 1
p_ind = ones(size(chi,3),1); % use only the one update given
elseif max(p_ind) <= size(dP,3) && numel(p_ind) == grouping
else
warning('Checkme, untested option')
keyboard
end
try
[AA, Atb] = get_LSQ_step_mex(chi,dO,dP,O,P,lambda_0, uint8(p_ind));
catch err
if any(strcmp(err.identifier, { 'MATLAB:UndefinedFunction','MATLAB:mex:ErrInvalidMEXFile'}))
path = fullfile(replace(mfilename('fullpath'), mfilename, ''), 'private');
mexcuda('-output', [path, '/get_LSQ_step_mex'], [path, '/get_LSQ_step_mex.cu'])
[AA, Atb] = get_LSQ_step_mex(chi,dO,dP,O,P,lambda_0, uint8(p_ind));
else
rethrow(err)
end
end
AA = Ggather(AA);
Atb = Ggather(Atb);
% is seems to be faster to get it first from GPU and then apply some
% oprations because the matrices are too small
AA = sum(AA,4);
Atb = sum(Atb,4);
AA = AA + lambda_LSQ*diag(diag(mean(AA,3)));
% the system of equations is so small that solving on CPU is good enough
[x1, x2] = solve_LSQ(AA(1,1,:), AA(2,1,:), AA(1,2,:), AA(2,2,:), Atb(1,1,:), Atb(2,1,:));
LSQ_step = cat(1, x1, x2);
else
if ~( par.share_probe || length(unique(p_ind)) == 1 )
% in case of multiple scans !!
% replicate the update back to the original dP size
dP = dP(:,:,p_ind);
end
tic
% prevent ill posed inversion, ideally it should be Garray(mean(abs(AA1)+abs(AA4))/2) but it i show
[AA1,AA2,AA4, Atb1,Atb2] = ...
Gfun(@get_optimal_step_lsq, chi,dO,dP,...
O,P, lambda_0);
AA1 = sum2(AA1);
AA2 = sum2(AA2);
AA4 = sum2(AA4);
Atb1 = sum2(Atb1);
Atb2 = sum2(Atb2);
% it seems faster to solve it on GPU than using pagefun on GPU
AA1 = Ggather(AA1);AA2 = Ggather(AA2);AA4 = Ggather(AA4);Atb1 = Ggather(Atb1);Atb2 = Ggather(Atb2);
AA3 = conj(AA2);
lambda = 0.5; % add some small regularization to avoid unstabilities
I = lambda*[mean(AA1), mean(AA4)];
AA = [ AA1+I(1), AA2; AA3, AA4+I(2)];
Atb= [ Atb1; Atb2];
[x1, x2] = solve_LSQ(AA(1,1,:), AA(2,1,:), AA(1,2,:), AA(2,2,:), Atb(1,1,:), Atb(2,1,:));
LSQ_step = cat(1, x1, x2);
end
LSQ_step = max(0, real(LSQ_step));
LSQ_step = Ggather(LSQ_step);
% prevent unwanted oscilation of step gets too high
beta_probe = LSQ_step(2,1,:);
beta_object = LSQ_step(1,1,:);
beta_probe = (par.beta_probe *par.beta_LSQ)* beta_probe;
beta_object = (par.beta_object*par.beta_LSQ)* beta_object;
end
function [AA1,AA2,AA4, Atb1,Atb2] = ...
get_optimal_step_lsq(chi,dO,dP,O,P, lambda)
% fast kernel for estimation of optimal P and object steps
dOP = dO.*P;
dPO = dP.*O;
cdOP = conj(dOP);
cdPO = conj(dPO);
AA1 = real(dOP .* cdOP)+lambda;
AA2 = (dOP .* cdPO);
AA4 = real(dPO .* cdPO)+lambda;
Atb1 = real(cdOP .* chi);
Atb2 = real(cdPO .* chi);
end
function [x1, x2] = solve_LSQ(AA1, AA2, AA3, AA4, Atb1, Atb2)
% GPU kernel to solve simple 2x2 system of equations
det = (AA1.*AA4 - AA2.*AA3);
x1 = -conj(AA2.*Atb2-AA4.*Atb1) ./ det;
x2 = conj(AA1.*Atb2-AA3.*Atb1) ./ det;
end
@@ -0,0 +1,89 @@
% GET_VARIABLE_PROBE calculate variable probe for given mean/var probe and its evolution inputs
%
% probe = get_variable_probe(probe, probe_evolution, p_ind)
%
% ** probe [Nx,Ny,probe_modes,variable_modes] array, variable probe
% ** probe_evolution [Npos,variable_modes] array containing evolution of the varaible modes for each position
% ** p_ind indices containg corresponding probe id for each processed position
%
% returns:
% ++ probe [Nx,Ny,N] array, a different probe for each scan position
%
% see also: engines.GPU_MS.LSQML
% Academic License Agreement
%
% Source Code
%
% Introduction
% This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
% will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
% ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
%
% Terms and Conditions of the LICENSE
% 1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
% hereinafter set out and until termination of this license as set forth below.
% 2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
% or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
% LICENSEEs responsibility to ensure its proper use and the correctness of the results.
% 3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
% A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
% HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
% OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
% 4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
% "IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
% license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
% profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
% in the commercial use, application or exploitation of works similar to the PROGRAM.
% 5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
% another computing language:
% "Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
% Scherrer Institut, Switzerland."
%
% Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
% P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379382 (2008).
% (doi: 10.1126/science.1158573),
% for mixed coherent modes:
% P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 6871 (2013). (doi: 10.1038/nature11806),
% for LSQ-ML method
% M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
% for OPRP method
% M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
% and/or for multislice:
% E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 2908929108 (2016).
% 6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
% names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
% 7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
% agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
% make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
% © All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
% 8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
% 9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
% to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
% in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
% in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
% 10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
% the courts of Zürich, Switzerland.
%
%
function probe = get_variable_probe(probe, probe_evolution, p_ind)
Np_p = [size(probe,1),size(probe,2)];
probe = probe(:,:,p_ind,:);
if length(p_ind) == 1 % in case that only single probe is called
probe = reshape(probe,prod(Np_p),[]);
probe = reshape(probe * probe_evolution', Np_p(1), Np_p(2), []);
else % in case multiple scans with unshared probe
probe_out = 0;
for ii = 1:size(probe,4)
probe_out = probe_out + probe(:,:,:,ii).*reshape(probe_evolution(:,ii),1,1,[]);
end
probe = probe_out;
end
end
@@ -0,0 +1,465 @@
/*
Set complex views to complex object
mexcuda -output +engines/+GPU/get_optimal_LSQ_step_mex +engines/+GPU/get_optimal_LSQ_step_mex.cu
*/
#include "mex.h"
#include "gpu/mxGPUArray.h"
#include <math.h>
#include <stdio.h>
#include <iostream>
#include <list>
typedef const unsigned int cuint;
typedef const uint16_T cuint16;
#define MAX_BLOCK_DIM_SIZE 65535
/*
* Device code
*/
// allocate shared memory so that all functions can see it
extern __shared__ float sdata[];
const unsigned int MAX_IND_READ = 10000;
__constant__ uint8_T gC_pind[MAX_IND_READ];
int checkLastError(char * msg)
{
cudaError_t cudaStatus = cudaGetLastError();
if (cudaStatus != cudaSuccess) {
char err[512];
sprintf(err, "get_optimal_LSQ_step_ker failed \n %s: %s. \n", msg, cudaGetErrorString(cudaStatus));
mexPrintf(err);
return 1;
}
return 0;
}
/*********** fast inplace version of LSQ step calculation *************/
template <unsigned int blockSize>
__device__ void calculate_AA_matrix( const float2 *P_f, const float2 *O_f,const float2 *dP_f, const float2 *dO_f, const float2 *chi_f,
float &AA1, float2 &AA2,float2 &AA3, float &AA4,
float &Atb1, float &Atb2 , const float lambda,
cuint Np_x, cuint Np_y, cuint Npixz, cuint idz,
cuint Nblocks, const bool single_probe, cuint id, cuint tid)
{
float2 dO, dP, O, P, chi;
// load to local memory
cuint id3 = id + Np_x*Np_y*idz;
O = O_f[id3] ;
dO = dO_f[id3] ;
chi = chi_f[id3];
if (single_probe) {
// single shared 2D probe
P = P_f[id];
dP = dP_f[id];
} else {
// unshared probe => size(dp,3) == Nscans
dP = dP_f[id + (gC_pind[idz]-1)*Np_x*Np_y];
// position in 3D array
P = P_f[id3];
}
// make auxiliary variables
float2 dOP, dPO, cdPO, cdOP;
// dOP = dO.*P;
dOP.x = dO.x * P.x - dO.y * P.y;
dOP.y = dO.y * P.x + dO.x * P.y;
// dPO = dP.*O;
dPO.x = dP.x * O.x - dP.y * O.y;
dPO.y = dP.y * O.x + dP.x * O.y;
// cdOP = conj(dOP);
cdOP.x = dOP.x;
cdOP.y = -dOP.y;
// cdPO = conj(dPO);
cdPO.x = dPO.x;
cdPO.y = -dPO.y;
// AA1 = abs(dOP).^2+lambda;
AA1 = dOP.x * dOP.x + dOP.y * dOP.y ;
// AA2 = (dOP .* cdPO);
AA2.x = dOP.x * cdPO.x - dOP.y * cdPO.y ;
AA2.y = dOP.x * cdPO.y + dOP.x * cdPO.y ;
// AA3 = conj(AA2);
AA3.x = AA2.x;
AA3.y = -AA2.y;
// AA4 = abs(dPO)^2+lambda;
AA4 = dPO.x * dPO.x + dPO.y * dPO.y ;
// Atb1 = real(cdOP .* chi);
Atb1 = cdOP.x*chi.x - cdOP.y*chi.y;
// Atb2 = real(cdPO .* chi);
Atb2 = cdPO.x*chi.x - cdPO.y*chi.y;
// add to the shared gpu memory
sdata[tid ] = AA1;
sdata[tid+ blockSize] = AA2.x;
sdata[tid+2*blockSize] = AA2.y;
sdata[tid+3*blockSize] = AA3.x;
sdata[tid+4*blockSize] = AA3.y;
sdata[tid+5*blockSize] = AA4;
sdata[tid+6*blockSize] = Atb1;
sdata[tid+7*blockSize] = Atb2;
}
template <unsigned int blockSize>
__device__ void add_to_shared_array( cuint tid, cuint offset )
{
// another loop unrolling
sdata[tid + 0*blockSize] += sdata[tid + 0*blockSize + offset];
sdata[tid + 1*blockSize] += sdata[tid + 1*blockSize + offset];
sdata[tid + 2*blockSize] += sdata[tid + 2*blockSize + offset];
sdata[tid + 3*blockSize] += sdata[tid + 3*blockSize + offset];
sdata[tid + 4*blockSize] += sdata[tid + 4*blockSize + offset];
sdata[tid + 5*blockSize] += sdata[tid + 5*blockSize + offset];
sdata[tid + 6*blockSize] += sdata[tid + 6*blockSize + offset];
sdata[tid + 7*blockSize] += sdata[tid + 7*blockSize + offset];
}
template <unsigned int blockSize>
__device__ void reduce_shared_array( cuint tid )
{
// do reduction in shared mem using unrolled loops
if (blockSize >= 1024){ if (tid < 512) { add_to_shared_array<blockSize>(tid,512); } __syncthreads(); }
if (blockSize >= 512) { if (tid < 256) { add_to_shared_array<blockSize>(tid,256); } __syncthreads(); }
if (blockSize >= 256) { if (tid < 128) { add_to_shared_array<blockSize>(tid,128); } __syncthreads(); }
if (blockSize >= 128) { if (tid < 64) { add_to_shared_array<blockSize>(tid,64); } __syncthreads(); }
// why not do the same for all
if (blockSize >= 64) { if (tid < 32) { add_to_shared_array<blockSize>(tid,32); } __syncthreads(); }
if (blockSize >= 32) { if (tid < 16) { add_to_shared_array<blockSize>(tid,16); } __syncthreads(); }
if (blockSize >= 16) { if (tid < 8) { add_to_shared_array<blockSize>(tid,8); } __syncthreads(); }
if (blockSize >= 8) { if (tid < 4) { add_to_shared_array<blockSize>(tid,4); } __syncthreads(); }
if (blockSize >= 4) { if (tid < 2) { add_to_shared_array<blockSize>(tid,2); } __syncthreads(); }
if (blockSize >= 2) { if (tid < 1) { add_to_shared_array<blockSize>(tid,1); } __syncthreads(); }
}
// fast kernel for estimation of optimal probe and object steps
template <unsigned int blockSize>
__global__ void get_optimal_LSQ_step_ker( float2 const * P_f, float2 const * O_f,float2 const * dP_f, float2 const * dO_f,
float2 const * chi_f, const float lambda,
float2 * AA, float * Atb, cuint Np_x,cuint Np_y, cuint Npixz, cuint Nblocks, const bool single_probe) {
const mwSize tid = threadIdx.x;
// do only every second block
//cuint i = blockIdx.x*(blockSize*2) + threadIdx.x;
const mwSize i = blockIdx.x*(blockDim.x) + threadIdx.x;
const mwSize N2 = Np_x*Np_y;
mwSize AA_page_id, Atb_page_id;
float2 AA2, AA3;
float AA1, AA4, Atb1, Atb2;
for(int n = 0; n < 8; n++)
sdata[tid + n*blockSize ] = 0 ;
if(i < N2)
{
//for(int n = 0; n < 8*blockSize; n++)
// sdata[n] = 0 ;
// Page in a 3D matrix
for(int idz = 0; idz < Npixz; idz++)
{
unsigned int ii = i ;
// empty the share memory
for(int n = 0; n < 8; n++)
sdata[tid + n*blockSize ] = 0 ;
// get coeficients for the AA matrix + right size Atb vector and add them to the shared array
calculate_AA_matrix<blockSize>(P_f ,O_f ,dP_f ,dO_f ,chi_f ,
AA1, AA2, AA3, AA4, Atb1, Atb2, lambda, Np_x, Np_y, Npixz, idz, Nblocks,single_probe, ii, tid);
__syncthreads();
// reduce the shared memory data
reduce_shared_array<blockSize>( tid );
// write result for this block to global mem
if (tid == 0) {
// store data to the AA matrix
AA_page_id = 4*idz + 4*Npixz*blockIdx.x;
Atb_page_id = 2*idz + 2*Npixz*blockIdx.x;
AA[ 0 + AA_page_id].x = sdata[0*blockSize];
AA[ 0 + AA_page_id].y = 0; // needs to be set to zero or initalized to zero when created
AA[ 1 + AA_page_id].x = sdata[1*blockSize];
AA[ 1 + AA_page_id].y = sdata[2*blockSize];
AA[ 2 + AA_page_id].x = sdata[3*blockSize];
AA[ 2 + AA_page_id].y = sdata[4*blockSize];
AA[ 3 + AA_page_id].x = sdata[5*blockSize];
AA[ 3 + AA_page_id].y = 0;
Atb[ 0 + Atb_page_id] = sdata[6*blockSize];
Atb[ 1 + Atb_page_id] = sdata[7*blockSize];
}
}
}
}
unsigned int nextPow2( unsigned int x ) {
--x;
x |= x >> 1;
x |= x >> 2;
x |= x >> 4;
x |= x >> 8;
x |= x >> 16;
return ++x;
}
void getNumBlocksAndThreads(int n, int maxBlocks, int maxThreads, int &blocks, int &threads)
{
threads = (n < maxThreads*2) ? nextPow2((n + 1)/ 2) : maxThreads;
blocks = (n + (threads * 2 - 1)) / (threads * 2);
blocks = min(maxBlocks, blocks);
}
void mexFunction(int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[])
{
char const * const errId = "parallel:gpu:mexGPUExample:InvalidInput";
char const * const errMsg = "Invalid input to MEX file.";
// Check for proper number of arguments.
if (nrhs != 7)
mexErrMsgTxt("Seven input arguments required");
const mxGPUArray * m_chi = mxGPUCreateFromMxArray(prhs[0]);
if ((mxGPUGetClassID(m_chi) != mxSINGLE_CLASS) || (mxGPUGetComplexity(m_chi) != mxCOMPLEX)) {
mexPrintf("m_chi\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const float2 * p_chi = (float2 *)mxGPUGetDataReadOnly(m_chi);
const mxGPUArray * m_dO = mxGPUCreateFromMxArray(prhs[1]);
if ((mxGPUGetClassID(m_dO) != mxSINGLE_CLASS) || (mxGPUGetComplexity(m_dO) != mxCOMPLEX)) {
mexPrintf("m_dO\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const float2 * p_dO = (float2 *)mxGPUGetDataReadOnly(m_dO);
const mxGPUArray * m_dP = mxGPUCreateFromMxArray(prhs[2]);
if ((mxGPUGetClassID(m_dP) != mxSINGLE_CLASS) || (mxGPUGetComplexity(m_dP) != mxCOMPLEX)) {
mexPrintf("m_dP\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const float2 * p_dP = (float2 *)mxGPUGetDataReadOnly(m_dP);
const mxGPUArray * m_O = mxGPUCreateFromMxArray(prhs[3]);
if ((mxGPUGetClassID(m_O) != mxSINGLE_CLASS) || (mxGPUGetComplexity(m_O) != mxCOMPLEX)) {
mexPrintf("m_O\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const float2 * p_O = (float2 *)mxGPUGetDataReadOnly(m_O);
const mxGPUArray * m_P = mxGPUCreateFromMxArray(prhs[4]);
if ((mxGPUGetClassID(m_P) != mxSINGLE_CLASS) || (mxGPUGetComplexity(m_P) != mxCOMPLEX)) {
mexPrintf("m_P\n");
mexErrMsgIdAndTxt(errId, errMsg);
}
const float2 * p_P = (float2 *)mxGPUGetDataReadOnly(m_P);
const mxGPUArray * m_P_ind = mxGPUCreateFromMxArray(prhs[6]);
if (mxGPUGetClassID(m_P_ind) != mxUINT8_CLASS) {
mexPrintf("m_P_ind class %i\n", mxGPUGetClassID(m_P_ind));
mexErrMsgIdAndTxt(errId, errMsg);
}
const uint8_T * p_P_ind = (uint8_T *)mxGPUGetDataReadOnly(m_P_ind);
const unsigned int Npos = mxGPUGetNumberOfElements(m_P_ind);
if (Npos > MAX_IND_READ) {
mexErrMsgIdAndTxt(errId, "Maximal size of input block exceeded");
}
// Get dimension of probe and object
const unsigned int Ndims = (unsigned int)mxGPUGetNumberOfDimensions(m_chi);
if (Ndims != 3) {
mexErrMsgIdAndTxt(errId, "Inputs has to be 3 dimensional\n");
}
const mwSize * Npix = mxGPUGetDimensions(m_chi);
const mwSize * Npix_probe = mxGPUGetDimensions(m_P);
const mwSize * Npix_probe_upd = mxGPUGetDimensions(m_dP);
const mwSize Ndims_probe = mxGPUGetNumberOfDimensions(m_P);
const mwSize Ndims_probe_upd = mxGPUGetNumberOfDimensions(m_dP);
if ((Npix[2] != Npos)) {
mexErrMsgIdAndTxt(errId, "Number of probe indices has to match size of inputs (%i vs %i) \n", Npix[2], Npos);
}
if ((Npix_probe[2] != Npix[2]) && (Ndims_probe != 2)) {
mexErrMsgIdAndTxt(errId, "Dimension of probe has to match size of inputs (%i vs %i) \n", Npix_probe[2], Npix[2]);
}
float lambda = mxGetScalar(prhs[5]);
const bool single_probe =Ndims_probe == 2 ;
cudaMemcpyToSymbol(gC_pind, p_P_ind, Npos*sizeof(uint8_T), 0, cudaMemcpyHostToDevice);
checkLastError("after cudaMemcpyToSymbol pos");
// Choose a reasonably sized number of threads in each dimension for the block.
int maxThreads = 1024; // number of threads per block, does not work with 1024, I dont know why
int threads = 0, blocks = 0;
cuint n = Npix[0]*Npix[1];
threads = (n < maxThreads) ? nextPow2((n + 1)/ 2) : maxThreads;
blocks = (n + (threads - 1)) / (threads );
dim3 dimBlock(threads, 1, 1);
dim3 dimGrid(blocks, 1, 1);
// allocation size needed for shared GPU memory , it needs to reduce 2 float2 elements and 4 float elements
int smemSize = 8* threads * sizeof(float);
//mexPrintf("threads %i blocks %i smemSize %i \n", threads, blocks, smemSize);
// allocate output fields
mwSize matrix_size[4] = {2,2,Npix[2],blocks};
mxGPUArray * m_AA = mxGPUCreateGPUArray(
4,
matrix_size,
mxSINGLE_CLASS,
mxCOMPLEX,
MX_GPU_DO_NOT_INITIALIZE); // MX_GPU_DO_NOT_INITIALIZE , MX_GPU_INITIALIZE_VALUES
float2 * p_AA = (float2 *)mxGPUGetData(m_AA);
mwSize vector_size[4] = {2,1,Npix[2],blocks};
mxGPUArray * m_Atb = mxGPUCreateGPUArray(
4,
vector_size,
mxSINGLE_CLASS,
mxREAL,
MX_GPU_DO_NOT_INITIALIZE);
float * p_Atb = (float *)mxGPUGetData(m_Atb);
checkLastError("after dimThread");
switch (threads)
{
case 1024:
get_optimal_LSQ_step_ker< 1024><<< dimGrid, dimBlock, smemSize>>>( p_P, p_O,p_dP, p_dO, p_chi, lambda,
p_AA, p_Atb, Npix[0], Npix[1], Npix[2], blocks, single_probe);
break;
case 512:
get_optimal_LSQ_step_ker< 512><<< dimGrid, dimBlock, smemSize>>>( p_P, p_O,p_dP, p_dO, p_chi, lambda,
p_AA, p_Atb, Npix[0], Npix[1], Npix[2], blocks, single_probe);
break;
case 256:
get_optimal_LSQ_step_ker< 256><<< dimGrid, dimBlock, smemSize>>>( p_P, p_O,p_dP, p_dO, p_chi, lambda,
p_AA, p_Atb, Npix[0], Npix[1], Npix[2], blocks, single_probe);
break;
case 128:
get_optimal_LSQ_step_ker< 128><<< dimGrid, dimBlock, smemSize>>>( p_P, p_O,p_dP, p_dO, p_chi, lambda,
p_AA, p_Atb, Npix[0], Npix[1], Npix[2], blocks, single_probe);
break;
case 64:
get_optimal_LSQ_step_ker< 64><<< dimGrid, dimBlock, smemSize>>>( p_P, p_O,p_dP, p_dO, p_chi, lambda,
p_AA, p_Atb, Npix[0], Npix[1], Npix[2], blocks, single_probe);
break;
case 32:
get_optimal_LSQ_step_ker< 32><<< dimGrid, dimBlock, smemSize>>>( p_P, p_O,p_dP, p_dO, p_chi, lambda,
p_AA, p_Atb, Npix[0], Npix[1], Npix[2], blocks, single_probe);
break;
case 16:
get_optimal_LSQ_step_ker< 16><<< dimGrid, dimBlock, smemSize>>>( p_P, p_O,p_dP, p_dO, p_chi, lambda,
p_AA, p_Atb, Npix[0], Npix[1], Npix[2], blocks, single_probe);
break;
case 8:
get_optimal_LSQ_step_ker< 8><<< dimGrid, dimBlock, smemSize>>>( p_P, p_O,p_dP, p_dO, p_chi, lambda,
p_AA, p_Atb, Npix[0], Npix[1], Npix[2], blocks, single_probe);
break;
case 4:
get_optimal_LSQ_step_ker< 4><<< dimGrid, dimBlock, smemSize>>>( p_P, p_O,p_dP, p_dO, p_chi, lambda,
p_AA, p_Atb, Npix[0], Npix[1], Npix[2], blocks, single_probe);
break;
case 2:
get_optimal_LSQ_step_ker< 2><<< dimGrid, dimBlock, smemSize>>>( p_P, p_O,p_dP, p_dO, p_chi, lambda,
p_AA, p_Atb, Npix[0], Npix[1], Npix[2], blocks, single_probe);
break;
case 1:
get_optimal_LSQ_step_ker< 1><<< dimGrid, dimBlock, smemSize>>>( p_P, p_O,p_dP, p_dO, p_chi, lambda,
p_AA, p_Atb, Npix[0], Npix[1], Npix[2], blocks, single_probe);
break;
}
checkLastError("after kernel");
cudaThreadSynchronize();
checkLastError("after kernel");
// Wrap the result up as a MATLAB gpuArray for return.
plhs[0] = mxGPUCreateMxArrayOnGPU(m_AA);
plhs[1] = mxGPUCreateMxArrayOnGPU(m_Atb);
mxGPUDestroyGPUArray(m_P);
mxGPUDestroyGPUArray(m_O);
mxGPUDestroyGPUArray(m_dP);
mxGPUDestroyGPUArray(m_dO);
mxGPUDestroyGPUArray(m_chi);
mxGPUDestroyGPUArray(m_AA);
mxGPUDestroyGPUArray(m_Atb);
return;
}
@@ -0,0 +1,136 @@
% REFINE_OBJECT_UPDATE calculate improved update direction
% apply "overlap" constraint to get better estimate of the update direction
%
% [object_upd_sum,object_update_proj, cache] = ...
% refine_object_update(self, object_update_proj,object_upd_sum,layer_ids,scan_ids,g_ind,par, cache)
%
% ** self structure containing inputs: e.g. current reconstruction results, data, mask, positions, pixel size, ..
% ** object_update_proj [Nx, Ny, N] array, estimate of the object update for each scan position, ie conj(P)*chi
% ** object_upd_sum cell of object sized arrays containg previous optimal updates
% ** g_ind indices corresponding to the current group that is solved in parallel
% ** layer_ids id of the solved layer for multilayer ptycho
% ** scan_ids determines to which scan correponds each of the position
% ** par structure containing parameters for the engines
% ** cache structure with precalculated values to avoid unnecessary overhead
%
% returns:
% ++ object_upd_sum cell of object sized arrays containg updated optimal update
% ++ object_update_proj [Nx, Ny, N] array, estimate of the refiend object update for each scan position,
% ++ cache structure with precalculated values to avoid unnecessary overhead
%
%
% see also: engines.GPU_MS.LSQML
%
% Academic License Agreement
%
% Source Code
%
% Introduction
% This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
% will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
% ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
%
% Terms and Conditions of the LICENSE
% 1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
% hereinafter set out and until termination of this license as set forth below.
% 2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
% or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
% LICENSEEs responsibility to ensure its proper use and the correctness of the results.
% 3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
% A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
% HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
% OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
% 4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
% "IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
% license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
% profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
% in the commercial use, application or exploitation of works similar to the PROGRAM.
% 5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
% another computing language:
% "Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
% Scherrer Institut, Switzerland."
%
% Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
% P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379382 (2008).
% (doi: 10.1126/science.1158573),
% for mixed coherent modes:
% P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 6871 (2013). (doi: 10.1038/nature11806),
% for LSQ-ML method
% M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
% for OPRP method
% M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
% and/or for multislice:
% E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 2908929108 (2016).
% 6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
% names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
% 7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
% agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
% make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
% © All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
% 8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
% 9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
% to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
% in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
% in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
% 10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
% the courts of Zürich, Switzerland.
function [object_upd_sum,object_update_proj, cache] = ...
refine_object_update(self, object_update_proj,object_upd_sum,layer_ids,scan_ids,g_ind,par, cache)
import engines.GPU_MS.shared.*
import engines.GPU_MS.GPU_wrapper.*
import math.*
import utils.*
if par.share_object
obj_ids = 1;
else
obj_ids = unique(scan_ids);
end
if ~isinf(self.z_distance)
% only in nearfield mode , apply shift in the opposite direction
object_update_proj = apply_subpx_shift(object_update_proj .* cache.apodwin, self.modes{1}.sub_px_shift(g_ind,:) ) ./ cache.apodwin;
end
% calculate update direction
% apply "overlap" constraint to get better estimate
% of the update directin
if is_method(par, 'MLs')
for ll_tmp = obj_ids; object_upd_sum{ll_tmp,layer_ids}(:) = eps*1i; end
end
if par.delta_p == 0 % || par.Nlayers > 1 % layer_ids > 1
%no preconditioner as in the original ML method
object_upd_sum = set_views(object_upd_sum,object_update_proj,layer_ids,obj_ids, g_ind, cache, scan_ids);
%plotting.smart_figure(1231)
%plotting.imagesc3D(object_upd_sum{1,layer_ids})
%drawnow
object_update_proj = get_views(object_upd_sum,object_update_proj,layer_ids,obj_ids, g_ind, cache, scan_ids);
elseif par.delta_p > 0
% damped LSQ method (preconditioned update)
object_upd_sum = set_views(object_upd_sum,object_update_proj,layer_ids,obj_ids, g_ind, cache, scan_ids);
for ll_tmp = obj_ids
object_upd_precond{ll_tmp,1} = Gfun(@object_sum_update_Gfun, object_upd_sum{ll_tmp,layer_ids}, cache.illum_sum_0{ll_tmp},cache.MAX_ILLUM(ll_tmp)*(par.delta_p));
end
object_update_proj = get_views(object_upd_precond,object_update_proj,1,obj_ids, g_ind, cache, scan_ids);
if is_method(par, 'MLs')
object_upd_sum(:,layer_ids) = object_upd_precond(obj_ids);
end
else
error('Unimplemented option')
end
end
function object_upd_sum = object_sum_update_Gfun(object_upd_sum, obj_illum_sq_sum, max)
% final update is just weighted mean of the updared object views
object_upd_sum = object_upd_sum ./ sqrt(obj_illum_sq_sum.^2+ max.^2);
end
@@ -0,0 +1,139 @@
% REFINE_PROBE_UPDATE calculate improved update direction
% apply "overlap" constraint to get better estimate of the update direction
% also updates the variable probe estimate
%
% [ self,m_probe_update, probe_update, cache] = ...
% refine_probe_update(self, obj_proj, probe_update, chi,layer_ids,probe_id,p_ind,g_ind, par, cache)
%
% ** self structure containing inputs: e.g. current reconstruction results, data, mask, positions, pixel size, ..
% ** obj_proj [Nx, Ny, N] array, estimate of the object update for each scan position, ie conj(P)*chi
% ** probe_update cell of object sized arrays containg previous optimal updates
% ** chi indices corresponding to the current group that is solved in parallel
% ** layer_ids id of the solved layer for multilayer ptycho
% ** probe_id id of incoherent probe mode
% ** p_ind indices containg corresponding probe id for each processed position
% ** g_ind indices corresponding to the current group that is solved in parallel
% ** par structure containing parameters for the engines
% ** cache structure with precalculated values to avoid unnecessary overhead
%
% returns:
% ++ object_upd_sum cell of object sized arrays containg updated optimal update
% ++ object_update_proj [Nx, Ny, N] array, estimate of the refiend object update for each scan position,
% ++ cache structure with precalculated values to avoid unnecessary overhead
%
%
% see also: engines.GPU_MS.LSQML
%
% Academic License Agreement
%
% Source Code
%
% Introduction
% This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
% will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
% ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
%
% Terms and Conditions of the LICENSE
% 1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
% hereinafter set out and until termination of this license as set forth below.
% 2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
% or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
% LICENSEEs responsibility to ensure its proper use and the correctness of the results.
% 3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
% A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
% HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
% OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
% 4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
% "IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
% license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
% profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
% in the commercial use, application or exploitation of works similar to the PROGRAM.
% 5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
% another computing language:
% "Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
% Scherrer Institut, Switzerland."
%
% Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
% P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379382 (2008).
% (doi: 10.1126/science.1158573),
% for mixed coherent modes:
% P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 6871 (2013). (doi: 10.1038/nature11806),
% for LSQ-ML method
% M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
% for OPRP method
% M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
% and/or for multislice:
% E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 2908929108 (2016).
% 6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
% names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
% 7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
% agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
% make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
% © All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
% 8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
% 9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
% to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
% in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
% in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
% 10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
% the courts of Zürich, Switzerland.
function [ self,m_probe_update, probe_update, cache] = ...
refine_probe_update(self, obj_proj, probe_update, chi,layer_ids,probe_id,p_ind,g_ind, par, cache)
% get probe update direction
import engines.GPU_MS.shared.*
import engines.GPU_MS.LSQML.*
import engines.GPU_MS.GPU_wrapper.*
import math.*
import utils.*
if layer_ids > 1 % in case of multilayer object
m_probe_update = [];
return
end
if (probe_id == 1 && par.apply_subpix_shift && isinf(self.z_distance(end))) || is_used(par,'fly_scan')
probe_update = apply_subpx_shift(probe_update , -self.modes{min(end,probe_id)}.sub_px_shift(g_ind,:) );
end
if probe_id == 1
probe_update = apply_subpx_shift_fft(probe_update, -self.modes{min(end,probe_id)}.probe_fourier_shift(g_ind,:));
end
if par.share_probe || length(unique(p_ind)) == 1
% BETTER WAY: assume that sum(|obj_proj|^2,3) is close to 1
% and additionally use weighting based on confidence given by illum_sum_0
% => apriory weighting giving less importance to the less
% illuminated regions
%weight_proj = cache.illum_sum_0{1} ./ (cache.illum_sum_0{1}+0.01*cache.MAX_ILLUM(1));
%weight_proj = get_views({weight_proj},[],1,1, g_ind, cache);
%m_probe_update = mean( weight_proj.* probe_update,3);
% or originally was used simple average , good for object >> probe
m_probe_update = mean(probe_update,3); % calculate single update for all current positions
else % unshared probe and multiple scans in one group (ie shared object)
probe_ids = unique(p_ind);
m_probe_update = Gzeros([self.Np_p,length(probe_ids)], true);
for probe_id =probe_ids(:)'
m_probe_update(:,:,probe_id) = mean(probe_update(:,:,p_ind == probe_id),3); % calculate one update for each scan
end
end
if (par.variable_probe || par.variable_intensity) && probe_id == 1
% ORTHOGONAL PROBE RELAXATION (OPRP) EXTENSION - allow
% variable probe wavefront
% Odstrcil, M., et al. "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369.
% iterate over all sub probes
[self.probe{probe_id}, self.probe_evolution] = ...
update_variable_probe(self, self.probe{probe_id}, self.probe_evolution, m_probe_update,probe_update, obj_proj, chi,cache.illum_sum_0{probe_id}, p_ind, g_ind, cache, par);
end
% % apply probe constraints
% if probe_id == 1 && (check_option(self,'probe_support') || check_option(self,'probe_support_fft'))
% m_probe_update = apply_probe_contraints(m_probe_update, self.modes{probe_id});
% end
end
@@ -0,0 +1,162 @@
% UPDATE_OBJECT calculate improved update direction
% apply "overlap" constraint to get better estimate of the update direction
%
% [object, object_upd_sum] = update_object(self, object, object_upd_sum, layer,object_ids, g_ind, scan_ids, par, cache, beta_object)
%
% ** self structure containing inputs: e.g. current reconstruction results, data, mask, positions, pixel size, ..
% ** object cell of object arrays
% ** object_upd_sum cell of object sized arrays containg previous optimal updates
% ** layer_ids id of the solved layer for multilayer ptycho
% ** object_ids id of incoherent object mode (not implemented)
% ** g_ind indices corresponding to the current group that is solved in parallel
% ** scan_ids determines to which scan correponds each of the position
% ** par structure containing parameters for the engines
% ** cache structure with precalculated values to avoid unnecessary overhead
% ** beta_object (scalar) relaxation parameter of the update step
%
% returns:
% ++ object cell of object arrays, after update
% ++ object_upd_sum cell of object sized arrays containg updated optimal update
%
%
% see also: engines.GPU_MS.LSQML
%
% Academic License Agreement
%
% Source Code
%
% Introduction
% This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
% will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
% ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
%
% Terms and Conditions of the LICENSE
% 1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
% hereinafter set out and until termination of this license as set forth below.
% 2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
% or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
% LICENSEEs responsibility to ensure its proper use and the correctness of the results.
% 3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
% A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
% HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
% OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
% 4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
% "IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
% license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
% profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
% in the commercial use, application or exploitation of works similar to the PROGRAM.
% 5. LICENSEE agrees that it shall make the foobject_idswing acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
% another computing language:
% "Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
% Scherrer Institut, Switzerland."
%
% Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
% P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379382 (2008).
% (doi: 10.1126/science.1158573),
% for mixed coherent modes:
% P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 6871 (2013). (doi: 10.1038/nature11806),
% for LSQ-ML method
% M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
% for OPRP method
% M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
% and/or for multislice:
% E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 2908929108 (2016).
% 6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
% names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
% 7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
% agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
% make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the foobject_idswing copyright notice on any such copies:
% © All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
% 8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
% 9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
% to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
% in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
% in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
% 10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
% the courts of Zürich, Switzerland.
function [object, object_upd_sum] = update_object(self, object, object_upd_sum, layer,object_ids, g_ind, scan_ids, par, cache, beta_object)
import engines.GPU_MS.shared.*
import engines.GPU_MS.GPU_wrapper.*
import math.*
import utils.*
if par.share_object
obj_ids = 1;
else
obj_ids = unique([scan_ids{:}]);
end
% take single optimal value, works well for most of samples
% it is possible to use different weighting for each scan position but
% it may become less stable in some cases -> robusness is preferred
% in case of the MLc method take minimum of the LSQ updates from all
% subsets
if is_method(par, 'MLc')
% preconditioner should be applied on the total sum of all object_upd_sum
if par.delta_p > 0 % && par.Nlayers == 1
for kk = obj_ids
object_upd_sum{kk,layer} = Gfun(@object_sum_update_Gfun, object_upd_sum{kk,layer}, cache.illum_sum_0{kk},cache.MAX_ILLUM(kk)*(par.delta_p));
end
end
end
% calculate optimal step, apply at least different step for each object (scan)
for i = 1:length(g_ind)
for kk = obj_ids
ind = g_ind{i}(scan_ids{i} == kk);
if isempty(ind)
beta_object_avg(i,kk) = nan;
else
beta_object_avg(i,kk) = trimmean(beta_object(ind, layer), 10); %20240929 SK Edit
end
end
end
% take the most pesimistic estimate of the per object
beta_object_avg=nanmin(beta_object_avg,[],1);
% update each of the objects separately
for kk = obj_ids
if beta_object_avg(kk) > 0
object_upd_sum{kk,layer} = object_upd_sum{kk,layer}*beta_object_avg(kk);
object{kk,layer} = object{kk,layer}+object_upd_sum{kk,layer};
end
end
if verbose()> 3
% show applied subsets (update amplitude) and probe update amplitude
plotting.smart_figure(11)
Nobj = size(object_upd_sum,1);
for ll = 1:Nobj
subplot(Nobj,2,1+Nobj*(ll-1))
cla()
o = object_upd_sum{ll,layer}(cache.object_ROI{:});
o = min(abs(o), quantile(abs(o(:)), 0.999)) .* o ./ abs(o);
plotting.imagesc3D(o);
axis image xy off
hold all
fprintf('Object update norm: %g\n', norm2(object_upd_sum{ll,layer}(cache.object_ROI{:})))
% try
% for k = 1:length(g_ind)
% for i = unique(scan_ids{k})
% plot(self.probe_positions_0(g_ind{k}(scan_ids{k}==i),1)+self.Np_o(2)/2,self.probe_positions_0(g_ind{k}(scan_ids{k}==i),2)+self.Np_o(1)/2, '.')
% end
% end
% end
end
title('Object update')
end
end
function object_upd_sum = object_sum_update_Gfun(object_upd_sum, obj_illum_sq_sum, max)
% final update is just weighted mean of the updared object views
object_upd_sum = object_upd_sum ./ sqrt(obj_illum_sq_sum.^2+ max.^2);
end
@@ -0,0 +1,125 @@
% UPDATE_PROBE calculate improved update direction
% apply "overlap" constraint to get better estimate of the update direction
%
% probe = update_probe(probe, m_probe_update, par, p_ind, g_ind, beta_probe, Nind)
%
% ** self structure containing inputs: e.g. current reconstruction results, data, mask, positions, pixel size, ..
% ** object_update_proj [Nx, Ny, N] array, estimate of the object update for each scan position, ie conj(P)*chi
% ** object_upd_sum cell of object sized arrays containg previous optimal updates
% ** p_ind indices containg corresponding probe id for each processed position
% ** g_ind indices corresponding to the current group that is solved in parallel
% ** beta_probe (scalar) relaxation parameter of the update step
% ** Nind (int) number of groups that are solved serially
% returns:
% ++ probe cell of the updated probes
%
%
% see also: engines.GPU_MS.LSQML
%
% Academic License Agreement
%
% Source Code
%
% Introduction
% This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
% will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
% ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
%
% Terms and Conditions of the LICENSE
% 1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
% hereinafter set out and until termination of this license as set forth below.
% 2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
% or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
% LICENSEEs responsibility to ensure its proper use and the correctness of the results.
% 3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
% A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
% HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
% OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
% 4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
% "IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
% license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
% profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
% in the commercial use, application or exploitation of works similar to the PROGRAM.
% 5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
% another computing language:
% "Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
% Scherrer Institut, Switzerland."
%
% Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
% P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379382 (2008).
% (doi: 10.1126/science.1158573),
% for mixed coherent modes:
% P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 6871 (2013). (doi: 10.1038/nature11806),
% for LSQ-ML method
% M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
% for OPRP method
% M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
% and/or for multislice:
% E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 2908929108 (2016).
% 6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
% names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
% 7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
% agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
% make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
% © All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
% 8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
% 9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
% to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
% in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
% in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
% 10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
% the courts of Zürich, Switzerland.
function probe = update_probe(probe, m_probe_update, par, p_ind, g_ind, beta_probe, Nind)
import engines.GPU_MS.shared.*
import engines.GPU_MS.GPU_wrapper.*
import utils.verbose
%% update probe
beta_probe = beta_probe(g_ind);
probe_ids = unique(p_ind);
if is_method(par, 'MLc')
beta_probe = beta_probe / Nind; % in order to make the compact version closer to original ML method, the accumulated probe step per iteration should be 1
end
if (par.share_probe || par.Nscans == 1) && size(probe,3)==1
% most simple case, no multiprobe needed
probe = probe + m_probe_update .* mean(beta_probe);
elseif length(probe_ids) == 1
% variable probe extension with shared probe
probe(:,:,probe_ids,1) = probe(:,:,probe_ids,1) + m_probe_update .* mean(beta_probe);
else % unshared probe
% update each of the probes separately
for id = probe_ids(:)'
ind = p_ind == id;
beta = mean(beta_probe(ind));
probe(:,:,id,1) = Gfun(@upd_probe_Gfun, probe(:,:,id,1),m_probe_update(:,:,min(end,id)), beta);
end
end
if verbose()> 3
% show applied subsets (update amplitude) and probe update
% amplitude
plotting.smart_figure(11)
probe_modes = size(m_probe_update,3);
for ll = 1:probe_modes
subplot(probe_modes,2,2+probe_modes*(ll-1))
p = fftshift(fft2(fftshift(m_probe_update(:,:,ll))));
p = min(abs(p), quantile(abs(p(:)), 0.999)) .* p ./ abs(p);
plotting.imagesc3D(p);
axis off image xy
end
title('Probe update')
colormap bone
drawnow
end
end
function probe = upd_probe_Gfun(probe,probe_update, alpha_p)
probe = probe + alpha_p.*probe_update;
end
@@ -0,0 +1,224 @@
% UPDATE_VARIABLE_PROBE approximation of the OPRP method to get only the first orthogonal
% vector describing the probe
%
% [probe, probe_evolution] = ...
% update_variable_probe(self,probe, probe_evolution, m_probe_update,probe_update, obj_proj, chi, weights, p_ind, g_ind, cache, par)
%
%
%
% ** self structure containing inputs: e.g. current reconstruction results, data, mask, positions, pixel size, ..
% ** probe [Nx,Nx,probe_modes,variable_modes] variable probe modes
% ** probe_evolution [Npos,variable_modes] array containing evolution of the varaible modes for each position
% ** m_probe_update precalculated value of mean(dP,3)
% ** probe_update probe update, ie conj(O)*chi
% ** obj_proj [Nx,Ny,N] array, views of the object for each scan position
% ** chi [Nx,Ny,N] array, difference between original and updated exit-wave
% ** weights array of relaxation values for object pixel, reduce weight of regions with weak illumination in the variable probe calculation
% ** p_ind indices containg corresponding probe id for each processed position
% ** g_ind indices corresponding to the current group that is solved in parallel
% ** cache structure with precalculated values to avoid unnecessary overhead
% ** par structure containing parameters for the engines
%
% returns:
% ++ probe [Nx,Nx,probe_modes,variable_modes] updated variable modes
% ++ probe_evolution [Npos,variable_modes] updated array containing evolution of the varaible modes for each position
%
%
% see also: engines.GPU_MS.LSQML
%
% Academic License Agreement
%
% Source Code
%
% Introduction
% This license agreement sets forth the terms and conditions under which the PAUL SCHERRER INSTITUT (PSI), CH-5232 Villigen-PSI, Switzerland (hereafter "LICENSOR")
% will grant you (hereafter "LICENSEE") a royalty-free, non-exclusive license for academic, non-commercial purposes only (hereafter "LICENSE") to use the cSAXS
% ptychography MATLAB package computer software program and associated documentation furnished hereunder (hereafter "PROGRAM").
%
% Terms and Conditions of the LICENSE
% 1. LICENSOR grants to LICENSEE a royalty-free, non-exclusive license to use the PROGRAM for academic, non-commercial purposes, upon the terms and conditions
% hereinafter set out and until termination of this license as set forth below.
% 2. LICENSEE acknowledges that the PROGRAM is a research tool still in the development stage. The PROGRAM is provided without any related services, improvements
% or warranties from LICENSOR and that the LICENSE is entered into in order to enable others to utilize the PROGRAM in their academic activities. It is the
% LICENSEEs responsibility to ensure its proper use and the correctness of the results.
% 3. THE PROGRAM IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR
% A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. IN NO EVENT SHALL THE LICENSOR, THE AUTHORS OR THE COPYRIGHT
% HOLDERS BE LIABLE FOR ANY CLAIM, DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY ARISING FROM, OUT OF OR IN CONNECTION WITH THE PROGRAM OR THE USE
% OF THE PROGRAM OR OTHER DEALINGS IN THE PROGRAM.
% 4. LICENSEE agrees that it will use the PROGRAM and any modifications, improvements, or derivatives of PROGRAM that LICENSEE may create (collectively,
% "IMPROVEMENTS") solely for academic, non-commercial purposes and that any copy of PROGRAM or derivatives thereof shall be distributed only under the same
% license as PROGRAM. The terms "academic, non-commercial", as used in this Agreement, mean academic or other scholarly research which (a) is not undertaken for
% profit, or (b) is not intended to produce works, services, or data for commercial use, or (c) is neither conducted, nor funded, by a person or an entity engaged
% in the commercial use, application or exploitation of works similar to the PROGRAM.
% 5. LICENSEE agrees that it shall make the following acknowledgement in any publication resulting from the use of the PROGRAM or any translation of the code into
% another computing language:
% "Data processing was carried out using the cSAXS ptychography MATLAB package developed by the Science IT and the coherent X-ray scattering (CXS) groups, Paul
% Scherrer Institut, Switzerland."
%
% Additionally, any publication using the package, or any translation of the code into another computing language should cite for difference map:
% P. Thibault, M. Dierolf, A. Menzel, O. Bunk, C. David, F. Pfeiffer, High-resolution scanning X-ray diffraction microscopy, Science 321, 379382 (2008).
% (doi: 10.1126/science.1158573),
% for mixed coherent modes:
% P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 6871 (2013). (doi: 10.1038/nature11806),
% for LSQ-ML method
% M. Odstrcil, A. Menzel, M.G. Sicairos, Iterative least-squares solver for generalized maximum-likelihood ptychography, Optics Express, 2018
% for OPRP method
% M. Odstrcil, P. Baksh, S. A. Boden, R. Card, J. E. Chad, J. G. Frey, W. S. Brocklesby, "Ptychographic coherent diffractive imaging with orthogonal probe relaxation." Optics express 24.8 (2016): 8360-8369
% and/or for multislice:
% E. H. R. Tsai, I. Usov, A. Diaz, A. Menzel, and M. Guizar-Sicairos, X-ray ptychography with extended depth of field, Opt. Express 24, 2908929108 (2016).
% 6. Except for the above-mentioned acknowledgment, LICENSEE shall not use the PROGRAM title or the names or logos of LICENSOR, nor any adaptation thereof, nor the
% names of any of its employees or laboratories, in any advertising, promotional or sales material without prior written consent obtained from LICENSOR in each case.
% 7. Ownership of all rights, including copyright in the PROGRAM and in any material associated therewith, shall at all times remain with LICENSOR, and LICENSEE
% agrees to preserve same. LICENSEE agrees not to use any portion of the PROGRAM or of any IMPROVEMENTS in any machine-readable form outside the PROGRAM, nor to
% make any copies except for its internal use, without prior written consent of LICENSOR. LICENSEE agrees to place the following copyright notice on any such copies:
% © All rights reserved. PAUL SCHERRER INSTITUT, Switzerland, Laboratory for Macromolecules and Bioimaging, 2017.
% 8. The LICENSE shall not be construed to confer any rights upon LICENSEE by implication or otherwise except as specifically set forth herein.
% 9. DISCLAIMER: LICENSEE shall be aware that Phase Focus Limited of Sheffield, UK has an international portfolio of patents and pending applications which relate
% to ptychography and that the PROGRAM may be capable of being used in circumstances which may fall within the claims of one or more of the Phase Focus patents,
% in particular of patent with international application number PCT/GB2005/001464. The LICENSOR explicitly declares not to indemnify the users of the software
% in case Phase Focus or any other third party will open a legal action against the LICENSEE due to the use of the program.
% 10. This Agreement shall be governed by the material laws of Switzerland and any dispute arising out of this Agreement or use of the PROGRAM shall be brought before
% the courts of Zürich, Switzerland.
function [probe, probe_evolution] = ...
update_variable_probe(self,probe, probe_evolution, m_probe_update,probe_update, obj_proj, chi, weights, p_ind, g_ind, cache, par)
import math.*
import plotting.*
import engines.GPU_MS.GPU_wrapper.*
uids = unique(p_ind);
for kk = uids
if length(uids) == 1 % single or shared probe between the scans
% avoid memory copy is possible
probe_update_tmp = probe_update;
chi_tmp = chi;
obj_proj_tmp = obj_proj;
g_ind_tmp = g_ind;
block_size = length(g_ind);
else
% otherwise
block_ind = p_ind == kk;
probe_update_tmp = probe_update(:,:,block_ind);
obj_proj_tmp = obj_proj(:,:,block_ind);
chi_tmp = chi(:,:,block_ind);
g_ind_tmp = g_ind(block_ind);
block_size= sum(block_ind);
end
if par.variable_probe
% use some relaxation to avoid too faster changes
relax_U = min(0.1,block_size/self.Npos);
relax_V = 1;
% make probe_update_tmp orthogonal to the average update
probe_update_tmp = probe_update_tmp - m_probe_update(:,:,min(end,kk));
for ii = 1:par.variable_probe_modes
var_probe = probe(:,:,kk,1+ii);
probe_evol = probe_evolution(g_ind_tmp,1+ii); % evolution of the 1th SVD mode coeficient
[var_probe,probe_evol,probe_update_tmp] = get_first_SVD_mode(probe_update_tmp, var_probe, probe_evol,relax_U,relax_V, obj_proj_tmp, chi_tmp);
if ii < par.variable_probe_modes
% subtract projection of the updated var_probe from the
% probe_update_tmp to enforce orthogonality between the
% modes
projection = sum2(probe_update_tmp .* conj(var_probe)) ./ sum2(abs(var_probe).^2);
probe_update_tmp = probe_update_tmp - projection .* var_probe;
end
% return the updated vector to the probe array
probe(:,:,kk,1+ii) = var_probe;
probe_evolution(g_ind_tmp,1+ii) = probe_evol;
end
end
if par. variable_intensity
% correction to account for variable intensity
mean_probe = probe(:,:,kk,1);
% compare P*0 and chi to estimate best update of the intensity
[nom, denom] = Gfun(@get_coefs_intensity,chi_tmp, mean_probe, obj_proj_tmp);
probe_evolution(g_ind_tmp,1) = probe_evolution(g_ind_tmp,1) + 0.1* squeeze(Ggather(sum2(nom)./ sum2(denom)));
end
end
if any(g_ind==1) && utils.verbose() > 3
self.probe{1} = probe;
self.probe_evolution = probe_evolution;
plot_variable_probe(self, par)
drawnow
end
end
function [var_probe,probe_evol, probe_update] = get_first_SVD_mode(probe_update, var_probe, probe_evol, relax_U,relax_V, obj_proj, chi)
import engines.GPU_MS.GPU_wrapper.*
import math.*
import plotting.*
% get a weighting function => avoid effect of too strong noise
% around edges of the reconstructed region => improve robustness againts outliers
% weights = weights / max2(weights);
% weight_proj = get_views( weights, Gzeros(size(chi)),1,1, g_ind, cache);
weight_proj = 1;
%% calculate terms needed to calculate update of the variable probe
% => U term in SVD decomposition
[resid, proj, probe_update] = Gfun(@get_SVD_update,probe_update, weight_proj, var_probe, reshape(probe_evol,1,1,[]), norm(probe_evol));
% get update the variable probe
var_probe_upd = mean( resid .* mean2(proj), 3);
% apply update, prevent too large changes at the beginning of the covergence
var_probe = var_probe + relax_U*var_probe_upd / norm2(var_probe_upd);
%% equivalent but much slower code
%[U,S,V] = svd(reshape(weight_proj.*(probe_update - m_probe_update), prod(self.Np_p),[]), 0);
%var_probe = var_probe + relax_U*reshape(U(:,1), self.Np_p);
% keep the eigenprobe normalized
var_probe = var_probe ./ norm2(var_probe);
%% calculate optimal OPRP evolution coeficients
[num, denum] = Gfun(@get_SVD_evol,var_probe, obj_proj, chi);
num =Ggather(mean2(num));
denum = Ggather(mean2(denum));
% perform relaxed update => improve robustness againts outliers
probe_evol_upd = squeeze(num ./ (denum + 0.1*mean(denum,3))); % caclulate regularized update
% add to the coefficients that are already used in the currently
% used probe{1} variable
probe_evol = probe_evol + relax_V*probe_evol_upd;
end
%% GPU kernel merging
% SVD approximation => calculation of U
function [resid, proj, probe_update] = get_SVD_update(probe_update, weight_proj, var_probe, probe_evol, probe_evol_norm)
resid = weight_proj .* probe_update;
proj = (real(conj(resid) .* var_probe)+ probe_evol) / probe_evol_norm^2;
end
% SVD approximation => calculation of S*V
function [num, denum] = get_SVD_evol(var_probe, obj_proj, chi)
psi = var_probe .* obj_proj;
denum = abs( psi ).^2;
num = real(chi .* conj(psi));
end
function [nom1, denom1] = get_coefs_intensity(xi, P, O)
OP = O.*P;
nom1 = real(conj(OP) .* xi);
denom1 = abs(OP).^2;
end