mirror of
https://github.com/c-sooyoung/fold_slice.git
synced 2026-09-17 20:39:08 +09:00
initial commit
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
function [dof,pixel_size] = DOF_calculator(energy, det_pixel, det_N, distance, alpha)
|
||||
%Calculate theoreical depth of focus for X-ray ptychography
|
||||
|
||||
% Inputs:
|
||||
% **energy beam energy (keV)
|
||||
% **det_pixel detector pixel size (m)
|
||||
% **det_N # of pixels in the detector
|
||||
% **distance # sample to detector distance (m)
|
||||
% **alpha additional scaling coefficient
|
||||
% *returns*:
|
||||
% ++dof depth of focus for ptychography
|
||||
|
||||
lambda = 1.23984193e-9/energy; % wavelength (m)
|
||||
pixel_size = lambda*distance/(det_pixel)/det_N; %pixel size in ptycho reconstruction (m)
|
||||
dof = alpha * pixel_size^2/lambda;
|
||||
end
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
% FUNCTION IM = C2IMAGE(A)
|
||||
%
|
||||
% Returns a RGB image of complex array A where
|
||||
% the phase is mapped to hue, and the amplitude
|
||||
% is mapped to brightness.
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| Except where otherwise noted, this work is licensed under a |
|
||||
%| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
|
||||
%| International (CC BY-NC-SA 4.0) license. |
|
||||
%| |
|
||||
%| Copyright (c) 2017 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
%| |
|
||||
%| Author: CXS group, PSI |
|
||||
%*-----------------------------------------------------------------------*
|
||||
% You may use this code with the following provisions:
|
||||
%
|
||||
% If the code is fully or partially redistributed, or rewritten in another
|
||||
% computing language this notice should be included in the redistribution.
|
||||
%
|
||||
% If this code, or subfunctions or parts of it, is used for research in a
|
||||
% publication or if it is fully or partially rewritten for another
|
||||
% computing language the authors and institution should be acknowledged
|
||||
% in written form in the publication: “Data processing was carried out
|
||||
% using the “cSAXS matlab package” developed by the CXS group,
|
||||
% Paul Scherrer Institut, Switzerland.”
|
||||
% Variations on the latter text can be incorporated upon discussion with
|
||||
% the CXS group if needed to more specifically reflect the use of the package
|
||||
% for the published work.
|
||||
%
|
||||
% A publication that focuses on describing features, or parameters, that
|
||||
% are already existing in the code should be first discussed with the
|
||||
% authors.
|
||||
%
|
||||
% This code and subroutines are part of a continuous development, they
|
||||
% are provided “as they are” without guarantees or liability on part
|
||||
% of PSI or the authors. It is the user responsibility to ensure its
|
||||
% proper use and the correctness of the results.
|
||||
|
||||
function im = c2image(a, varargin)
|
||||
|
||||
|
||||
if ismatrix(a)
|
||||
absa = abs(a);
|
||||
phasea = angle(a);
|
||||
|
||||
% (optional second argument can switch between various plotting modes)
|
||||
abs_range = [];
|
||||
if nargin==2
|
||||
m = varargin{1};
|
||||
elseif nargin==3
|
||||
m = varargin{1};
|
||||
abs_range = varargin{2};
|
||||
else
|
||||
m = 1;
|
||||
end
|
||||
|
||||
if isempty(abs_range)
|
||||
nabsa = absa/max(max(absa));
|
||||
else
|
||||
nabsa = (absa - abs_range(1))/(abs_range(2) - abs_range(1));
|
||||
nabsa(nabsa < 0) = 0;
|
||||
nabsa(nabsa > 1) = 1;
|
||||
end
|
||||
|
||||
switch m
|
||||
case 1
|
||||
im_hsv = zeros([size(a) 3]);
|
||||
im_hsv(:,:,1) = mod(phasea,2*pi)/(2*pi);
|
||||
im_hsv(:,:,2) = 1;
|
||||
im_hsv(:,:,3) = nabsa;
|
||||
im = hsv2rgb(im_hsv);
|
||||
case 2
|
||||
im_hsv = ones([size(a) 3]);
|
||||
im_hsv(:,:,1) = mod(phasea,2*pi)/(2*pi);
|
||||
im_hsv(:,:,2) = nabsa;
|
||||
im = hsv2rgb(im_hsv);
|
||||
end
|
||||
elseif ndims(a)==3
|
||||
sz = size(a);
|
||||
|
||||
im_hsv = zeros([sz 3]);
|
||||
im = zeros([sz 3]);
|
||||
|
||||
for ii=1:sz(3)
|
||||
absa = abs(a(:,:,ii));
|
||||
phasea = angle(a(:,:,ii));
|
||||
|
||||
% (optional second argument can switch between various plotting modes)
|
||||
abs_range = [];
|
||||
if nargin==2
|
||||
m = varargin{1};
|
||||
elseif nargin==3
|
||||
m = varargin{1};
|
||||
abs_range = varargin{2};
|
||||
else
|
||||
m = 1;
|
||||
end
|
||||
|
||||
if isempty(abs_range)
|
||||
nabsa = absa/max(max(absa));
|
||||
else
|
||||
nabsa = (absa - abs_range(1))/(abs_range(2) - abs_range(1));
|
||||
nabsa(nabsa < 0) = 0;
|
||||
nabsa(nabsa > 1) = 1;
|
||||
end
|
||||
|
||||
|
||||
switch m
|
||||
case 1
|
||||
im_hsv(:,:,ii,1) = mod(phasea,2*pi)/(2*pi);
|
||||
im_hsv(:,:,ii,2) = 1;
|
||||
im_hsv(:,:,ii,3) = nabsa;
|
||||
case 2
|
||||
im_hsv(:,:,ii,1) = mod(phasea,2*pi)/(2*pi);
|
||||
im_hsv(:,:,ii,2) = nabsa;
|
||||
end
|
||||
im(:,:,ii,:) = hsv2rgb(squeeze(im_hsv(:,:,ii,:)));
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
%check_ptycho_recon.m
|
||||
%Examine ML reconstructionsml
|
||||
@@ -0,0 +1,30 @@
|
||||
function [rgb_data] = convert_to_rgb(data)
|
||||
%Convert complex data into rgb image showing both magnitude and phase
|
||||
% Detailed explanation goes here
|
||||
|
||||
[W,H] = size(data);
|
||||
adata = abs(data);
|
||||
|
||||
alpha = 1e-3;
|
||||
tmp= sort(adata(:));
|
||||
MAX = tmp(ceil(end*(1-alpha)));
|
||||
ind = adata > MAX;
|
||||
data(ind) = MAX * data(ind) ./ abs(data(ind));
|
||||
adata = abs(data);
|
||||
range = sp_quantile(adata(:), [1e-2, 1-1e-2],10);
|
||||
adata = (adata - range(1) ) ./ ( range(2) - range(1) );
|
||||
|
||||
ang_data = angle(data);
|
||||
hue = mod(ang_data+2.5*pi, 2*pi)/(2*pi);
|
||||
hsv_data = [ hue(:) , ones(W*H,1), adata(:) ];
|
||||
|
||||
hsv_data = min(max(0, hsv_data),1);
|
||||
|
||||
|
||||
rgb_data = hsv2rgb(hsv_data);
|
||||
|
||||
rgb_data = reshape(rgb_data, W,H,3);
|
||||
rgb_data = min(1,rgb_data);
|
||||
|
||||
end
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
% FIND_RECONSTRUCTION_ROI_EXTERNAL precalculate the reconstruction regions
|
||||
% Modified by YJ for external use outside the GPU engines
|
||||
% ROI is consistent with "obj_proj" in LSQML.m
|
||||
%
|
||||
% [oROI, oROI_vec, sub_px_shift] = find_reconstruction_ROI2( positions,Np_o, Np_p )
|
||||
%
|
||||
% ** positions Npox*2 vector of scanning positions
|
||||
% ** Np_o object size
|
||||
% ** Np_p probe size
|
||||
%
|
||||
% returns:
|
||||
% ++ oROI cell array contaning range for each view
|
||||
% ++ oROI_vec cell array contaning range for each view in vector shape
|
||||
% ++ sub_px_shift subpixel rounding errors, used for subpixel shift
|
||||
%
|
||||
|
||||
function [oROI, oROI_vec, sub_px_shift] = find_reconstruction_ROI_external( positions,Np_o, Np_p )
|
||||
|
||||
positions = positions(:,[2,1]);
|
||||
positions = positions + ceil(Np_o/2-Np_p/2);
|
||||
sub_px_shift = positions - round(positions);
|
||||
|
||||
sub_px_shift = sub_px_shift(:,[2,1]); % return to the original XY coordinates
|
||||
|
||||
positions = round(positions);
|
||||
|
||||
range = [min(positions), max(positions)+ Np_p];
|
||||
|
||||
if any(range(1:2) < 0) || any(range(3:4) > Np_o)
|
||||
error('Object size is too small, not enough space for probes !! \nposition range: %i %i %i %i, \nobject size: %i %i ', range(1), range(2), range(3), range(4), Np_o(1), Np_o(2))
|
||||
end
|
||||
|
||||
oROI = cell(2,1);
|
||||
for dim = 1:2
|
||||
oROI{dim} = [positions(:,dim),positions(:,dim)+ Np_p(dim)-1];
|
||||
oROI{dim} = uint32(oROI{dim});
|
||||
end
|
||||
|
||||
if nargout > 1
|
||||
Npos = length(positions);
|
||||
oROI_vec = cell(Npos,2);
|
||||
for ii = 1:Npos
|
||||
for i = 1:2
|
||||
oROI_vec{ii,i} = (oROI{i}(ii,1)):(oROI{i}(ii,2));
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,523 @@
|
||||
%IMAGESC3D 3D wrapper for imagesc
|
||||
% imagesc3D supports the same parameters as Matlab's imagesc. In addition, the following
|
||||
% parameters can be set
|
||||
%
|
||||
% init_frame... starting frame number (default 1)
|
||||
% slider_axis... axis along which you want to use imagesc (default 3)
|
||||
% fps... frames per second (default 25); will be adjusted by a factor of 1.2 to account for internal overhead
|
||||
% title_list... individual title for each frame (default {})
|
||||
% loop... run in a loop (default false)
|
||||
% reset_frame... stop resets frame to init_frame (default false)
|
||||
% autoplay... stark movie automatically (default false)
|
||||
% slider_position... slider position [left bottom width height] (default center of axis)
|
||||
% play_position... play button position [left bottom width height]
|
||||
% edit_position... edit box position [left bottom width height]
|
||||
% show_play_button... show/hide button; needs to be visible if loop=true; (default true)
|
||||
% show_edit_box... show/hide box
|
||||
% fnct... data processing function
|
||||
% order... change slice order in stack
|
||||
% save_movie... specify filename if a movie shall be written
|
||||
% movie_quality... image quality of the saved movie
|
||||
%
|
||||
% Complex images will be converted to RGB using c2image.
|
||||
%
|
||||
% If you are not using 'autplay', you can also set a global title instead
|
||||
% of a title list (similar to imagesc) and use '%d' to get the slice number
|
||||
% title('Random block - slice %d')
|
||||
%
|
||||
%
|
||||
% EXAMPLES:
|
||||
% imagesc3D(rand(256, 256, 100), 'fps', 10, 'loop', true)
|
||||
% imagesc3D(rand(256, 256)*1j)
|
||||
% imagesc3D(rand(20, 256, 256), 'slider_axis', 1);
|
||||
%
|
||||
%
|
||||
% Additionally, you can use imagesc/imagesc3D routines and trigger the movie by
|
||||
% calling the play method of a specified axis:
|
||||
%
|
||||
% figure(1);
|
||||
% imagesc3D(rand(256, 256, 100), 'fps', 20);
|
||||
% title('Random block - slice %d');
|
||||
% colorbar();
|
||||
% ax = gca;
|
||||
% ax.play();
|
||||
%
|
||||
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| Except where otherwise noted, this work is licensed under a |
|
||||
%| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
|
||||
%| International (CC BY-NC-SA 4.0) license. |
|
||||
%| |
|
||||
%| Copyright (c) 2017 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
%| |
|
||||
%| Author: CXS group, PSI |
|
||||
%*-----------------------------------------------------------------------*
|
||||
% You may use this code with the following provisions:
|
||||
%
|
||||
% If the code is fully or partially redistributed, or rewritten in another
|
||||
% computing language this notice should be included in the redistribution.
|
||||
%
|
||||
% If this code, or subfunctions or parts of it, is used for research in a
|
||||
% publication or if it is fully or partially rewritten for another
|
||||
% computing language the authors and institution should be acknowledged
|
||||
% in written form in the publication: “Data processing was carried out
|
||||
% using the “cSAXS matlab package” developed by the CXS group,
|
||||
% Paul Scherrer Institut, Switzerland.”
|
||||
% Variations on the latter text can be incorporated upon discussion with
|
||||
% the CXS group if needed to more specifically reflect the use of the package
|
||||
% for the published work.
|
||||
%
|
||||
% A publication that focuses on describing features, or parameters, that
|
||||
% are already existing in the code should be first discussed with the
|
||||
% authors.
|
||||
%
|
||||
% This code and subroutines are part of a continuous development, they
|
||||
% are provided “as they are” without guarantees or liability on part
|
||||
% of PSI or the authors. It is the user responsibility to ensure its
|
||||
% proper use and the correctness of the results.
|
||||
|
||||
function imagesc3D(varargin)
|
||||
%import math.isint
|
||||
%import plotting.c2image
|
||||
|
||||
ax_img = {};
|
||||
if nargin == 1
|
||||
img = varargin{1};
|
||||
vararg = {};
|
||||
elseif nargin == 3 && isnumeric(varargin{1}) && isnumeric(varargin{2}) && (islogical(varargin{3}) || isnumeric(varargin{3}))
|
||||
img = varargin{3};
|
||||
ax_img = varargin(1:2);
|
||||
vararg = {};
|
||||
elseif (islogical(varargin{1}) || isnumeric(varargin{1})) && ischar(varargin{2})
|
||||
% assume that first argument is images, and next are
|
||||
% string+arguments
|
||||
img = varargin{1};
|
||||
vararg = varargin(2:end);
|
||||
elseif isnumeric(varargin{1}) && isnumeric(varargin{2}) && (islogical(varargin{3}) || isnumeric(varargin{3}))
|
||||
% assume that first two arguments are axis,and third is images, and next are
|
||||
% string+arguments
|
||||
ax_img = varargin(1:2);
|
||||
img = varargin{3};
|
||||
vararg = varargin(4:end);
|
||||
else
|
||||
error('Unknown combination of parameters')
|
||||
end
|
||||
|
||||
ax = gca;
|
||||
pos = ax.Position;
|
||||
slider_default = [pos(1)+pos(3)/2-0.06 pos(2)-0.1 0.14 0.05];
|
||||
play_default = [slider_default(1)-0.1 pos(2)-0.1 0.08 0.05];
|
||||
edit_default = [slider_default(1)+slider_default(3)+0.01 slider_default(2) 0.08 0.05];
|
||||
|
||||
par = inputParser;
|
||||
par.addParameter('fps', 25, @isnumeric) % maximal frame rate
|
||||
par.addParameter('init_frame', 1, @isnumeric) % starting frame number
|
||||
par.addParameter('title_list', {}, @iscell) % list of titles for each frame
|
||||
par.addParameter('slider_axis',3, @isnumeric) % array axis
|
||||
par.addParameter('loop', false, @islogical) % loop
|
||||
par.addParameter('reset_frame', false, @islogical) % stop resets frame to init_frame
|
||||
par.addParameter('autoplay', false, @islogical) % start loop automatically
|
||||
par.addParameter('slider_position',slider_default, @isnumeric) % slider position; [left bottom width height]
|
||||
par.addParameter('play_position',play_default, @isnumeric) % slider position; [left bottom width height]
|
||||
par.addParameter('edit_position', edit_default, @isnumeric) % edit position; [left bottom width height]
|
||||
par.addParameter('show_play_button',true, @islogical) % array axis
|
||||
par.addParameter('show_edit_box', true, @islogical) % edit box
|
||||
par.addParameter('fnct', @(x)x) % data processing function
|
||||
par.addParameter('order', 1:size(img,3), @isnumeric) % change slice order in stack
|
||||
par.addParameter('plot_residua', false, @islogical) % plot residua in the image
|
||||
par.addParameter('save_movie', '', @ischar) % specify filename if a movie shall be written
|
||||
par.addParameter('movie_quality', 80, @isnumeric) % movie quality
|
||||
|
||||
|
||||
par.parse(vararg{:})
|
||||
vars = par.Results;
|
||||
|
||||
vars.fps = vars.fps *1.2; % correct for overhead
|
||||
|
||||
% permute the array to slide along diferent axis
|
||||
switch vars.slider_axis
|
||||
case 1
|
||||
img = rot90(permute(img,[2,3,1]));
|
||||
case 2
|
||||
img = rot90(permute(img,[1,3,2]));
|
||||
end
|
||||
if any(cellfun(@(x)(strcmpi(x, 'order')), par.UsingDefaults))
|
||||
% redefine the order just in case that the axis were swapped, but only
|
||||
% if there is not use preference
|
||||
vars.order = 1:size(img,3);
|
||||
end
|
||||
|
||||
|
||||
if ~isempty(vars.title_list)
|
||||
assert(length(vars.title_list) == size(img,3), 'Number of titles has to correspond to number of frames')
|
||||
end
|
||||
|
||||
sz = size(img,3);
|
||||
|
||||
im = imhandles(gcf);
|
||||
ax = gca;
|
||||
if ~isprop(ax, 'index')
|
||||
ax.addprop('index');
|
||||
ax.index = length(im)+1;
|
||||
else
|
||||
if isprop(ax, 'play_handle')
|
||||
delete(ax.play_handle);
|
||||
end
|
||||
if isprop(ax, 'slider_handle')
|
||||
delete(ax.slider_handle);
|
||||
end
|
||||
if isprop(ax, 'edit_handle')
|
||||
delete(ax.edit_handle);
|
||||
end
|
||||
if isprop(ax, 'vars')
|
||||
ax.vars = [];
|
||||
end
|
||||
end
|
||||
|
||||
if sz>1
|
||||
% checks
|
||||
vars.init_frame = round(vars.init_frame);
|
||||
|
||||
if vars.init_frame > sz || vars.init_frame < 1
|
||||
warning('Initial frame exceeds stack size.')
|
||||
vars.init_frame = 1;
|
||||
end
|
||||
|
||||
vars.vargin = ax_img;
|
||||
|
||||
if ~ax.isprop('img')
|
||||
ax.addprop('img');
|
||||
end
|
||||
|
||||
ax.img = img;
|
||||
|
||||
if ~ax.isprop('play')
|
||||
ax.addprop('play');
|
||||
end
|
||||
ax.play = @(x)play(x);
|
||||
|
||||
if ~ax.isprop('stop')
|
||||
ax.addprop('stop');
|
||||
end
|
||||
ax.stop = @(x)stop(x);
|
||||
|
||||
if ~ax.isprop('update_fig')
|
||||
ax.addprop('update_fig');
|
||||
end
|
||||
ax.update_fig = @(x)update_fig(x);
|
||||
|
||||
|
||||
%%% set handles
|
||||
|
||||
% slider
|
||||
slider_handle=uicontrol(gcf,'Style','slider','Max',sz,'Min',1,...
|
||||
'Value',vars.init_frame,'SliderStep',[1/(sz-1) 10/(sz-1)],...
|
||||
'Units','normalized','Position',vars.slider_position);
|
||||
if ~isprop(slider_handle, 'ax_index')
|
||||
slider_handle.addprop('ax_index');
|
||||
slider_handle.ax_index = ax.index;
|
||||
end
|
||||
if ~ax.isprop('slider_handle')
|
||||
ax.addprop('slider_handle');
|
||||
ax.slider_handle = slider_handle;
|
||||
elseif ax.isprop('slider_handle') && ~ax.slider_handle.isvalid
|
||||
ax.slider_handle = slider_handle;
|
||||
end
|
||||
|
||||
% play button
|
||||
if vars.show_play_button
|
||||
visible_button = 'on';
|
||||
else
|
||||
visible_button = 'off';
|
||||
if vars.loop
|
||||
warning('Loop can not be aborted without buttons. Setting ''loop'' back to ''false''.');
|
||||
vars.loop = false;
|
||||
end
|
||||
end
|
||||
|
||||
play_handle=uicontrol(gcf,'Style','pushbutton','string','Play',...
|
||||
'Units','normalized','Position',vars.play_position, 'Visible', visible_button);
|
||||
if ~isprop(play_handle, 'ax_index')
|
||||
play_handle.addprop('ax_index');
|
||||
play_handle.ax_index = ax.index;
|
||||
end
|
||||
if ~ax.isprop('play_handle')
|
||||
ax.addprop('play_handle');
|
||||
ax.play_handle = play_handle;
|
||||
elseif ax.isprop('play_handle') && ~ax.play_handle.isvalid
|
||||
ax.play_handle = play_handle;
|
||||
end
|
||||
if ~ax.isprop('vars')
|
||||
ax.addprop('vars');
|
||||
ax.vars = vars;
|
||||
else
|
||||
ax.vars = vars;
|
||||
end
|
||||
set(play_handle,'Callback',{@play_callback,ax});
|
||||
|
||||
|
||||
% text edit
|
||||
if vars.show_edit_box
|
||||
visible_box = 'on';
|
||||
else
|
||||
visible_box = 'off';
|
||||
end
|
||||
edit_handle = uicontrol('style','edit','units','normalized', 'Position', vars.edit_position, 'Visible', visible_box);
|
||||
set(edit_handle, 'Callback', {@edit_callback, ax});
|
||||
if ~ax.isprop('edit_handle')
|
||||
ax.addprop('edit_handle');
|
||||
ax.edit_handle = edit_handle;
|
||||
elseif ax.isprop('edit_handle') && ~ax.edit_handle.isvalid
|
||||
ax.edit_handle = edit_handle;
|
||||
end
|
||||
if ~isprop(edit_handle, 'ax_index')
|
||||
edit_handle.addprop('ax_index');
|
||||
edit_handle.ax_index = ax.index;
|
||||
end
|
||||
|
||||
|
||||
% set callback functions
|
||||
set(slider_handle,'Callback',{@slider_callback,ax});
|
||||
set(edit_handle, 'String', num2str(get(ax.slider_handle,'Value')));
|
||||
|
||||
|
||||
if vars.autoplay
|
||||
play_callback(ax, ax, ax);
|
||||
end
|
||||
|
||||
update_fig(ax)
|
||||
|
||||
else
|
||||
% standard imagesc should be enough
|
||||
if ax.isprop('update_title') || ax.isprop('play_handle') || ax.isprop('vars')
|
||||
if ax.isprop('vars') && isfield(ax.vars, 'slider_handle')
|
||||
ax.vars = rmfield(ax.vars, 'slider_handle');
|
||||
end
|
||||
if ax.isprop('play_handle')
|
||||
delete(ax.play_handle);
|
||||
end
|
||||
cla(ax);
|
||||
end
|
||||
|
||||
img = gather(vars.fnct(img));
|
||||
|
||||
if ~isreal(img)
|
||||
img = c2image(img);
|
||||
end
|
||||
if ~isempty(ax_img)
|
||||
imagesc(ax_img{:}, img);
|
||||
else
|
||||
imagesc(img);
|
||||
end
|
||||
if ~isempty(vars.title_list)
|
||||
title(ax, vars.title_list{1}, 'Interpreter', 'none')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
% plotting function
|
||||
function update_fig(ax)
|
||||
%import math.isint
|
||||
%import plotting.c2image
|
||||
|
||||
% im = imhandles(gcf);
|
||||
vars = ax.vars;
|
||||
slice = round(get(ax.slider_handle,'Value'));
|
||||
slice = max(1, min(length(vars.order), slice));
|
||||
|
||||
% FIXME: everything works better without following lines
|
||||
% sl = gcbo();
|
||||
% if ~isempty(sl)
|
||||
% ax = findobj('index', sl.ax_index);
|
||||
% end
|
||||
|
||||
img = gather(vars.fnct(squeeze(ax.img(:,:,vars.order(slice),:))));
|
||||
|
||||
if ~isreal(img)
|
||||
img = c2image(img);
|
||||
end
|
||||
if vars.plot_residua
|
||||
[residua{2},residua{1}] = find(abs(utils.findresidues(img))>0.1);
|
||||
|
||||
end
|
||||
|
||||
% if the current axis is empty, use imagesc with remaining arguments
|
||||
if ~ax.isprop('update_title')
|
||||
ax.addprop('update_title');
|
||||
ax.addprop('user_title');
|
||||
ax.update_title = true;
|
||||
if ~isempty(vars.vargin)
|
||||
imagesc(vars.vargin{:}, img);
|
||||
else
|
||||
imagesc(img);
|
||||
end
|
||||
hold all
|
||||
if vars.plot_residua && ~isempty(residua{1})
|
||||
plot(residua{:},'or')
|
||||
elseif vars.plot_residua
|
||||
plot(0,0,'or')
|
||||
end
|
||||
hold off
|
||||
addlistener(ax.Title, 'String', 'PostSet', @(gt, event)callback_title_post(ax, ax));
|
||||
else
|
||||
% if we just need to update the figure, only update the data
|
||||
ax_data = ax.findobj('Type', 'Image');
|
||||
ax_data.CData = img;
|
||||
if vars.plot_residua
|
||||
ax_data = ax.findobj('Type', 'Line');
|
||||
ax_data(1).XData = residua{1};
|
||||
ax_data(1).YData = residua{2};
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
% write title
|
||||
if isempty(vars.title_list)
|
||||
ax.update_title = false;
|
||||
if ~isempty(ax.user_title)
|
||||
title_text = sprintf(ax.user_title, vars.order(slice));
|
||||
title(ax, title_text, 'Interpreter', 'none');
|
||||
end
|
||||
ax.update_title = true;
|
||||
else
|
||||
if ~isempty(vars.title_list)
|
||||
title(ax, vars.title_list{vars.order(slice)}, 'Interpreter', 'none')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% Callback subfunctions %%%
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
function slider_callback(~,~,ax)
|
||||
% ob = gco;
|
||||
% vars.ax_index = ob.ax_index;
|
||||
if ax.isprop('edit_handle')
|
||||
set(ax.edit_handle, 'string', num2str(round(get(ax.slider_handle,'Value'))));
|
||||
end
|
||||
update_fig(ax)
|
||||
drawnow()
|
||||
|
||||
end
|
||||
|
||||
|
||||
function callback_title_post(ax, ~, ~)
|
||||
if ax.update_title
|
||||
ax.user_title = ax.Title.String;
|
||||
try
|
||||
ax.Title.String = sprintf(ax.user_title, get(ax.slider_handle,'Value'));
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function play_callback(~,~,ax)
|
||||
% ax = findobj('index', ax.slider_handle.ax_index);
|
||||
vars = ax.vars;
|
||||
if ax.isprop('slider_handle') && ax.slider_handle.isvalid
|
||||
update_slider = true;
|
||||
else
|
||||
update_slider = false;
|
||||
end
|
||||
if ax.isprop('edit_handle') && ax.edit_handle.isvalid
|
||||
update_edit = true;
|
||||
else
|
||||
update_edit = false;
|
||||
end
|
||||
try
|
||||
switch get(ax.play_handle,'string')
|
||||
case 'Play'
|
||||
if ~isempty(vars.save_movie)
|
||||
disp(['Saving movie to ' vars.save_movie]);
|
||||
writeobj = VideoWriter(vars.save_movie);
|
||||
writeobj.Quality=vars.movie_quality;
|
||||
writeobj.FrameRate=vars.fps;
|
||||
|
||||
open(writeobj);
|
||||
vars.writeobj = writeobj;
|
||||
end
|
||||
set(ax.play_handle,'string','Stop')
|
||||
sz = size(ax.img,3);
|
||||
pos = round(get(ax.slider_handle,'Value'));
|
||||
if pos == sz
|
||||
set(ax.slider_handle,'Value',1);
|
||||
pos = 1;
|
||||
end
|
||||
while pos <=sz
|
||||
|
||||
if strcmp(get(ax.play_handle,'string'), 'Play')
|
||||
break
|
||||
end
|
||||
if update_slider
|
||||
set(ax.slider_handle,'Value',pos)
|
||||
end
|
||||
if update_edit
|
||||
set(ax.edit_handle, 'String', num2str(pos));
|
||||
end
|
||||
|
||||
update_fig(ax)
|
||||
pause(1/vars.fps)
|
||||
if vars.loop && pos == sz
|
||||
pos = 1;
|
||||
else
|
||||
pos = pos+1;
|
||||
end
|
||||
if vars.save_movie
|
||||
currFrame = getframe;
|
||||
writeVideo(vars.writeobj,currFrame);
|
||||
end
|
||||
|
||||
end
|
||||
set(ax.play_handle,'string','Play')
|
||||
if vars.reset_frame
|
||||
set(ax.slider_handle,'Value',vars.init_frame)
|
||||
end
|
||||
if vars.save_movie
|
||||
close(vars.writeobj);
|
||||
end
|
||||
case 'Stop'
|
||||
set(ax.play_handle,'string','Play')
|
||||
if vars.save_movie
|
||||
close(vars.writeobj);
|
||||
end
|
||||
end
|
||||
catch
|
||||
if ~ax.isprop('play_handle')
|
||||
fprintf('Lost connection to figure instance.\n')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function edit_callback(~,~, ax)
|
||||
str=get(ax.edit_handle,'String');
|
||||
|
||||
if isempty(str2num(str))
|
||||
warndlg('Input must be numerical');
|
||||
set(ax.edit_handle, 'string', num2str(round(get(ax.slider_handle,'Value'))));
|
||||
else
|
||||
set(ax.slider_handle,'Value',str2num(str))
|
||||
update_fig(ax)
|
||||
drawnow()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
function play(ax)
|
||||
play_callback(ax.vars, ax.vars, ax);
|
||||
end
|
||||
|
||||
function stop(ax)
|
||||
set(ax.play_handle,'string','Play')
|
||||
set(ax.slider_handle,'Value',ax.vars.init_frame)
|
||||
end
|
||||
@@ -0,0 +1,201 @@
|
||||
% IMAGESC_HSV for plotting complex valued arrays , similar to imagesc3D but with more options
|
||||
% imagesc_hsv(varargin)
|
||||
%
|
||||
% ** varargin see the code
|
||||
|
||||
%
|
||||
% 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
|
||||
% LICENSEE’s 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, 379–382 (2008).
|
||||
% (doi: 10.1126/science.1158573),
|
||||
% for mixed coherent modes:
|
||||
% P. Thibault and A. Menzel, Reconstructing state mixtures from diffraction measurements, Nature 494, 68–71 (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, 29089–29108 (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 imagesc_hsv(varargin)
|
||||
|
||||
import utils.*
|
||||
import math.*
|
||||
|
||||
par = inputParser;
|
||||
par.addOptional('data', [])
|
||||
par.addParameter('scale', nan , @isnumeric )
|
||||
par.addParameter('clim', [] , @isnumeric )
|
||||
par.addParameter('inverse', false , @islogical ) % use white background
|
||||
par.addParameter('show_ROI', false , @islogical ) % show only intersting area
|
||||
par.addParameter('points', [] , @isnumeric ) % plot dots
|
||||
par.addParameter('enhance_contrast', false , @islogical ) % plot dots
|
||||
par.addParameter('axis', [] , @isnumeric ) % plot dots
|
||||
par.addParameter('stabilize_phase', true , @islogical ) % plot dots
|
||||
par.addParameter('show', true , @islogical ) % plot dots
|
||||
|
||||
par.parse(varargin{:})
|
||||
r = par.Results;
|
||||
data = r.data;
|
||||
clim = r.clim;
|
||||
|
||||
if all(data(:) == 0)
|
||||
warning('Empty data to plot')
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
|
||||
[W,H] = size(data);
|
||||
|
||||
if ~isempty(r.axis)
|
||||
X = linspace(r.axis(1),r.axis(2),W)*1e6;
|
||||
Y = linspace(r.axis(3),r.axis(4),H)*1e6;
|
||||
else
|
||||
if ~isnan(r.scale)
|
||||
scale = ones(2,1).*r.scale(:);
|
||||
X = [-W/2:W/2-1]* scale(1)*1e6;
|
||||
Y = [-H/2:H/2-1]* scale(2)*1e6;
|
||||
else
|
||||
X = 1:W; Y = 1:H;
|
||||
end
|
||||
end
|
||||
if r.show_ROI
|
||||
asum = abs(sum(data,3));
|
||||
try
|
||||
T1 = (graythresh_new((sum(asum,1))));
|
||||
T2 = (graythresh_new((sum(asum,2))));
|
||||
asum(:,sum(asum,1) < T1) = 0;
|
||||
asum(sum(asum,2) < T2,:) = 0;
|
||||
[ROI] = get_ROI(asum > 0.01*quantile(asum(:), 0.99), 0);
|
||||
data = data(ROI{:});
|
||||
X = X(ROI{1});
|
||||
Y = Y(ROI{2});
|
||||
catch
|
||||
warning('ROI estimation failed')
|
||||
end
|
||||
end
|
||||
[W,H] = size(data);
|
||||
|
||||
if ~isempty(clim)
|
||||
ind_min = abs(data) < clim(1);
|
||||
ind_max = abs(data) > clim(2);
|
||||
data(ind_min) = data(ind_min) ./ abs(data(ind_min)) * clim(1);
|
||||
data(ind_max) = data(ind_max) ./ abs(data(ind_max)) * clim(2);
|
||||
end
|
||||
|
||||
adata = abs(data);
|
||||
|
||||
|
||||
|
||||
alpha = 1e-3;
|
||||
tmp= sort(adata(:));
|
||||
MAX = tmp(ceil(end*(1-alpha)));
|
||||
ind = adata > MAX;
|
||||
data(ind) = MAX * data(ind) ./ abs(data(ind));
|
||||
if r.enhance_contrast
|
||||
data = data ./ sqrt(alpha+abs(data));
|
||||
clim = sqrt(clim);
|
||||
end
|
||||
if r.stabilize_phase
|
||||
data = stabilize_phase(data, abs(data), abs(data), 'remove_ramp', false);
|
||||
end
|
||||
|
||||
adata = abs(data);
|
||||
|
||||
if isempty(clim)
|
||||
range = sp_quantile(adata(:), [1e-2, 1-1e-2],10);
|
||||
else
|
||||
range = clim;
|
||||
end
|
||||
%clim
|
||||
adata = (adata - range(1) ) ./ ( range(2) - range(1) );
|
||||
ang_data = angle(data);
|
||||
|
||||
if r.enhance_contrast && r.stabilize_phase
|
||||
ang_range = max(abs(sp_quantile(ang_data(:), [1e-2, 1-1e-2],10)));
|
||||
ang_range = max(1e-3, ang_range);
|
||||
ang_data = 2*pi*ang_data ./ (2* ang_range);
|
||||
end
|
||||
|
||||
|
||||
if r.inverse
|
||||
hue = mod(ang_data+1.5*pi, 2*pi)/(2*pi);
|
||||
hsv_data = [ hue(:) , adata(:), ones(W*H,1) ];
|
||||
else
|
||||
hue = mod(ang_data+2.5*pi, 2*pi)/(2*pi);
|
||||
hsv_data = [ hue(:) , ones(W*H,1), adata(:) ];
|
||||
end
|
||||
hsv_data = min(max(0, hsv_data),1);
|
||||
|
||||
|
||||
rgb_data = hsv2rgb(hsv_data);
|
||||
|
||||
rgb_data = reshape(rgb_data, W,H,3);
|
||||
rgb_data = min(1,rgb_data);
|
||||
|
||||
|
||||
if r.show
|
||||
hh = imagesc(Y,X, rgb_data );
|
||||
axis image
|
||||
end
|
||||
|
||||
if r.show
|
||||
% Get the parent Axes of the image
|
||||
axis image
|
||||
|
||||
if ~isempty(r.points) && ~any(isnan(r.scale))
|
||||
hold on
|
||||
points = r.scale.*1e6.*r.points;
|
||||
plot( points(:,1),points(:,2), '.w')
|
||||
hold off
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
% ISINT returns true if all values of X are integers, but class can be arbitrary
|
||||
% numerical array
|
||||
%
|
||||
% Inputs:
|
||||
% **x - checked array
|
||||
% *optional*
|
||||
% **prec - precision threshold used to decide whether the number is still integer, default = 0.01
|
||||
% *returns*:
|
||||
% is_integer - scalar bool
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| Except where otherwise noted, this work is licensed under a |
|
||||
%| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
|
||||
%| International (CC BY-NC-SA 4.0) license. |
|
||||
%| |
|
||||
%| Copyright (c) 2017 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
%| |
|
||||
%| Author: CXS group, PSI |
|
||||
%*-----------------------------------------------------------------------*
|
||||
% You may use this code with the following provisions:
|
||||
%
|
||||
% If the code is fully or partially redistributed, or rewritten in another
|
||||
% computing language this notice should be included in the redistribution.
|
||||
%
|
||||
% If this code, or subfunctions or parts of it, is used for research in a
|
||||
% publication or if it is fully or partially rewritten for another
|
||||
% computing language the authors and institution should be acknowledged
|
||||
% in written form in the publication: “Data processing was carried out
|
||||
% using the “cSAXS matlab package” developed by the CXS group,
|
||||
% Paul Scherrer Institut, Switzerland.”
|
||||
% Variations on the latter text can be incorporated upon discussion with
|
||||
% the CXS group if needed to more specifically reflect the use of the package
|
||||
% for the published work.
|
||||
%
|
||||
% A publication that focuses on describing features, or parameters, that
|
||||
% are already existing in the code should be first discussed with the
|
||||
% authors.
|
||||
%
|
||||
% This code and subroutines are part of a continuous development, they
|
||||
% are provided “as they are” without guarantees or liability on part
|
||||
% of PSI or the authors. It is the user responsibility to ensure its
|
||||
% proper use and the correctness of the results.
|
||||
|
||||
function is_integer = isint(x, prec)
|
||||
if nargin < 2
|
||||
prec = 1e-2;
|
||||
end
|
||||
is_integer = all(abs(round(x(:)) - x(:)) < prec);
|
||||
end
|
||||
@@ -0,0 +1,63 @@
|
||||
% FUNCTION [u_1, H, h, dH] = near_field_evolution(u_0, z, lambda, extent, use_ASM_only)
|
||||
% Description: nearfield evolution function, it automatically swithch
|
||||
% between ASM and Fraunhofer propagation
|
||||
|
||||
function [u_1, H, h, dH] = near_field_evolution(u_0, z, lambda, extent, use_ASM_only)
|
||||
|
||||
|
||||
H = [];
|
||||
h = [];
|
||||
u_1 = [];
|
||||
dH = [];
|
||||
|
||||
|
||||
if nargin < 5
|
||||
use_ASM_only = false;
|
||||
end
|
||||
|
||||
extent = extent(:)' .* ones(1,2);
|
||||
if z == 0
|
||||
H = 1;
|
||||
u_1 = u_0;
|
||||
return
|
||||
end
|
||||
if z == inf
|
||||
return
|
||||
end
|
||||
|
||||
Npix = size(u_0);
|
||||
|
||||
xgrid = (0.5+(-Npix(1)/2:Npix(1)/2-1))/Npix(1);
|
||||
ygrid = (0.5+(-Npix(2)/2:Npix(2)/2-1))/Npix(2);
|
||||
|
||||
k = 2 * pi / lambda(1);
|
||||
|
||||
% Undesamplling parameter
|
||||
F = mean( extent.^2 ./ (lambda(1) .* z .* Npix ));
|
||||
|
||||
if abs(F) < 1 && ~use_ASM_only
|
||||
% farfield propagation
|
||||
warning('Farfield regime, F/Npix=%g', F )
|
||||
Xrange = xgrid*extent(1);
|
||||
Yrange = ygrid*extent(2);
|
||||
[X,Y] = meshgrid(Xrange, Yrange);
|
||||
h = exp(1i*k*z +1i*k/(2*z) * (X'.^2 + Y'.^2));
|
||||
|
||||
% this serves as low pass filter for the far nearfield
|
||||
H = ifftshift(fft2(fftshift(h)));
|
||||
H = H / abs(H(end/2+1, end/2+1)); % renormalize to conserve flux in image
|
||||
else
|
||||
% standard ASM
|
||||
kx = 2 * pi .*xgrid / extent(1) * Npix(1);
|
||||
ky = 2 * pi .*ygrid / extent(2) * Npix(2);
|
||||
[Kx, Ky] = meshgrid(kx, ky);
|
||||
|
||||
dH = ( -1i*(Kx'.^2+Ky'.^2)/(2*k) );
|
||||
|
||||
H = exp( 1i*z*sqrt( k^2 - Kx'.^2-Ky'.^2)); % it make it a bit more sensitive to z distance
|
||||
h = [];
|
||||
end
|
||||
|
||||
u_1 = ifft2( bsxfun(@times, ifftshift(H), fft2(u_0)));
|
||||
end
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Unwrapping phase based on Ghiglia and Romero (1994) based on weighted and unweighted least-square method
|
||||
% URL: https://doi.org/10.1364/JOSAA.11.000107
|
||||
% Inputs:
|
||||
% * psi: wrapped phase from -pi to pi
|
||||
% * weight: weight of the phase (optional, default: all ones)
|
||||
% Output:
|
||||
% * phi: unwrapped phase from the weighted (or unweighted) least-square phase unwrapping
|
||||
% Author: Muhammad F. Kasim (University of Oxford, 2016)
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
function phi = phase_unwrap(psi, weight)
|
||||
if (nargin < 2) % unweighted phase unwrap
|
||||
% get the wrapped differences of the wrapped values
|
||||
dx = [zeros([size(psi,1),1]), wrapToPi(diff(psi, 1, 2)), zeros([size(psi,1),1])];
|
||||
dy = [zeros([1,size(psi,2)]); wrapToPi(diff(psi, 1, 1)); zeros([1,size(psi,2)])];
|
||||
rho = diff(dx, 1, 2) + diff(dy, 1, 1);
|
||||
|
||||
% get the result by solving the poisson equation
|
||||
phi = solvePoisson(rho);
|
||||
|
||||
else % weighted phase unwrap
|
||||
% check if the weight has the same size as psi
|
||||
if (~all(size(weight) == size(psi)))
|
||||
error('Argument error: Size of the weight must be the same as size of the wrapped phase');
|
||||
end
|
||||
|
||||
% vector b in the paper (eq 15) is dx and dy
|
||||
dx = [wrapToPi(diff(psi, 1, 2)), zeros([size(psi,1),1])];
|
||||
dy = [wrapToPi(diff(psi, 1, 1)); zeros([1,size(psi,2)])];
|
||||
|
||||
% multiply the vector b by weight square (W^T * W)
|
||||
WW = weight .* weight;
|
||||
WWdx = WW .* dx;
|
||||
WWdy = WW .* dy;
|
||||
|
||||
% applying A^T to WWdx and WWdy is like obtaining rho in the unweighted case
|
||||
WWdx2 = [zeros([size(psi,1),1]), WWdx];
|
||||
WWdy2 = [zeros([1,size(psi,2)]); WWdy];
|
||||
rk = diff(WWdx2, 1, 2) + diff(WWdy2, 1, 1);
|
||||
normR0 = norm(rk(:));
|
||||
|
||||
% start the iteration
|
||||
eps = 1e-6;
|
||||
k = 0;
|
||||
phi = zeros(size(psi));
|
||||
while (~all(rk == 0))
|
||||
zk = solvePoisson(rk);
|
||||
k = k + 1;
|
||||
if (k == 1) pk = zk;
|
||||
else
|
||||
betak = sum(sum(rk .* zk)) / sum(sum(rkprev .* zkprev));
|
||||
pk = zk + betak * pk;
|
||||
end
|
||||
|
||||
% save the current value as the previous values
|
||||
rkprev = rk;
|
||||
zkprev = zk;
|
||||
|
||||
% perform one scalar and two vectors update
|
||||
Qpk = applyQ(pk, WW);
|
||||
alphak = sum(sum(rk .* zk)) / sum(sum(pk .* Qpk));
|
||||
phi = phi + alphak * pk;
|
||||
rk = rk - alphak * Qpk;
|
||||
|
||||
% check the stopping conditions
|
||||
if ((k >= numel(psi)) || (norm(rk(:)) < eps * normR0)) break; end;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function phi = solvePoisson(rho)
|
||||
% solve the poisson equation using dct
|
||||
dctRho = dct2(rho);
|
||||
[N, M] = size(rho);
|
||||
[I, J] = meshgrid([0:M-1], [0:N-1]);
|
||||
dctPhi = dctRho ./ 2 ./ (cos(pi*I/M) + cos(pi*J/N) - 2);
|
||||
dctPhi(1,1) = 0; % handling the inf/nan value
|
||||
|
||||
% now invert to get the result
|
||||
phi = idct2(dctPhi);
|
||||
|
||||
end
|
||||
|
||||
% apply the transformation (A^T)(W^T)(W)(A) to 2D matrix
|
||||
function Qp = applyQ(p, WW)
|
||||
% apply (A)
|
||||
dx = [diff(p, 1, 2), zeros([size(p,1),1])];
|
||||
dy = [diff(p, 1, 1); zeros([1,size(p,2)])];
|
||||
|
||||
% apply (W^T)(W)
|
||||
WWdx = WW .* dx;
|
||||
WWdy = WW .* dy;
|
||||
|
||||
% apply (A^T)
|
||||
WWdx2 = [zeros([size(p,1),1]), WWdx];
|
||||
WWdy2 = [zeros([1,size(p,2)]); WWdy];
|
||||
Qp = diff(WWdx2,1,2) + diff(WWdy2,1,1);
|
||||
end
|
||||
@@ -0,0 +1,51 @@
|
||||
% SP_QUANTILE sparse quantile, just make a fast guess of the quantile value
|
||||
% on a downsampled array. Useful for estimation of the optimal imagesc
|
||||
% limits
|
||||
%
|
||||
% Qval = sp_quantile(array,quantile,reduce)
|
||||
%
|
||||
% Inputs:
|
||||
% **array - inputs ndim array
|
||||
% **quantile - number or vector from 0 to 1 denoting quantiles
|
||||
% **reduce - use every n-th element for calculation
|
||||
% *returns*:
|
||||
% ++Q - scalar or vector of quantiles of the reduced array
|
||||
|
||||
%*-----------------------------------------------------------------------*
|
||||
%| |
|
||||
%| Except where otherwise noted, this work is licensed under a |
|
||||
%| Creative Commons Attribution-NonCommercial-ShareAlike 4.0 |
|
||||
%| International (CC BY-NC-SA 4.0) license. |
|
||||
%| |
|
||||
%| Copyright (c) 2017 by Paul Scherrer Institute (http://www.psi.ch) |
|
||||
%| |
|
||||
%| Author: CXS group, PSI |
|
||||
%*-----------------------------------------------------------------------*
|
||||
% You may use this code with the following provisions:
|
||||
%
|
||||
% If the code is fully or partially redistributed, or rewritten in another
|
||||
% computing language this notice should be included in the redistribution.
|
||||
%
|
||||
% If this code, or subfunctions or parts of it, is used for research in a
|
||||
% publication or if it is fully or partially rewritten for another
|
||||
% computing language the authors and institution should be acknowledged
|
||||
% in written form in the publication: “Data processing was carried out
|
||||
% using the “cSAXS matlab package” developed by the CXS group,
|
||||
% Paul Scherrer Institut, Switzerland.”
|
||||
% Variations on the latter text can be incorporated upon discussion with
|
||||
% the CXS group if needed to more specifically reflect the use of the package
|
||||
% for the published work.
|
||||
%
|
||||
% A publication that focuses on describing features, or parameters, that
|
||||
% are already existing in the code should be first discussed with the
|
||||
% authors.
|
||||
%
|
||||
% This code and subroutines are part of a continuous development, they
|
||||
% are provided “as they are” without guarantees or liability on part
|
||||
% of PSI or the authors. It is the user responsibility to ensure its
|
||||
% proper use and the correctness of the results.
|
||||
|
||||
function Qval = sp_quantile(x,q,reduce)
|
||||
x = x(1:reduce:end);
|
||||
Qval = quantile(x,q);
|
||||
end
|
||||
Reference in New Issue
Block a user