Files
fold_slice/+utils/goldsteinunwrap2.m
T
2026-08-07 15:56:42 +09:00

293 lines
12 KiB
Matlab
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
% Implementation of Goldstein unwrap algorithm based on location of
% residues and introduction of branchcuts.
% R. M. Goldstein, H. A. Zebker and C. L. Werner, Radio Science 23, 713-720
% (1988).
% Inputs
% fase Phase in radians, wrapped between (-pi,pi)
% disp (optional) = 1 to show progress (will slow down code)
% will also display the branch cuts
% start (optional) [y,x] position to start unwrapping. Typically faster
% at the center of the array
% Outputs
% faserecon Unwrapped phase ( = fase where phase could not be unwrapped)
% shadow = 1 where phase could not be unwrapped
% 31 August, 2010 - Acknowledge if used
% Modified 20 Sept 2010 - Find a safe area to unwrap around the first point
%*-----------------------------------------------------------------------*
%|                                                                       |
%|  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 [faserecon shadow] = goldsteinunwrap2(fase,disp,start)
display('Unwrapping with Goldstein algorithm')
[nr nc] = size(fase);
if nargin < 2
disp = 0;
end
if nargin <3
nrstart = round(nr/2);
ncstart = round(nc/2);
else
nrstart = start(1);
ncstart = start(2);
end
residues = wrapToPi(fase(2:end,1:end-1) - fase(1:end-1,1:end-1));
residues = residues + wrapToPi(fase(2:end,2:end) - fase(2:end,1:end-1));
residues = residues + wrapToPi(fase(1:end-1,2:end) - fase(2:end,2:end));
residues = residues + wrapToPi(fase(1:end-1,1:end-1) - fase(1:end-1,2:end));
residues = residues/(2*pi);
%%% Find residues
[posr,posc] = find(round(residues)==1);
respos = [posr posc ones(length(posr),1)];
[posr,posc] = find(round(residues)==-1);
resneg = [posr posc -ones(length(posr),1)];
%[posr,posc] = find(round(residues)~=0);
%res = [posr posc];
%res = [respos;resneg];
nres = length(respos(:,1))+length(resneg(:,1));
display(['Found ' num2str(nres) ' residues'])
if nres == 0,
faserecon = unwrap(unwrap(fase')');
shadow = faserecon*0;
return;
end
%%% Find minimum length walls
%currentwall = residues*0;
currentwall = zeros(nr+2,nc+2);
%currentwallcharge = 0;
%wallsegdone = 0;
%currentwall(res(1,1)+1,res(1,2)+1) = 1;
for ii = 1:min(length(respos(:,1)),length(resneg(:,1))),
dist = (respos(1,1) - resneg(:,1)).^2 + (respos(1,2)-resneg(:,2)).^2;
ind = find(dist == min(dist),1,'first');
if sqrt(dist(ind)) < min(nc,nr)/4,%/4
currentwall( respos(1,1)+1,min(respos(1,2),resneg(ind,2))+1 : max(respos(1,2),resneg(ind,2))+1 ) = 1;
currentwall(min(resneg(ind,1),respos(1,1))+1:max(resneg(ind,1),respos(1,1))+1,resneg(ind,2)+1) = 1;
respos = respos(2:end,:); % Remove from respos
resaux = resneg(1:ind-1,:);
resaux = [resaux;resneg(ind+1:end,:)];
resneg = resaux;
else % Wall too long between them, send to window edge
% for respos
distedges = [nr-respos(1,1) respos(1,1) nc-respos(1,2) respos(1,2)]; %upper, lower, right, left
switch min(distedges)
case distedges(1) %upper
currentwall(respos(1,1)+1:nr+2, respos(1,2)+1 ) = 1;
case distedges(2) %lower
currentwall(1:respos(1,1)+1, respos(1,2)+1) = 1;
case distedges(3); %right
currentwall(respos(1,1)+1, respos(1,2)+1:nc+2) = 1;
case distedges(4); %left
currentwall(respos(1,1)+1, 1:respos(1,2)+1) = 1;
end
% for resneg
distedges = [nr-resneg(ind,1) resneg(ind,1) nc-resneg(ind,2) resneg(ind,2)]; %upper, lower, right, left
switch min(distedges)
case distedges(1) %upper
currentwall(resneg(ind,1)+1:nr+2, resneg(ind,2)+1 ) = 1;
case distedges(2) %lower
currentwall(1:resneg(ind,1)+1, resneg(ind,2)+1) = 1;
case distedges(3); %right
currentwall(resneg(ind,1)+1, resneg(ind,2)+1:nc+2) = 1;
case distedges(4); %left
currentwall(resneg(ind,1)+1, 1:resneg(ind,2)+1) = 1;
end
end
end
% else
% error('Need to implement for unbalanced charge residues')
% end
% Branch cuts for unpaired residues
res = [respos; resneg];
display([num2str(length(res(:,1))) ' unpaired residues'])
for ii = 1:length(res(:,1)),
distedges = [nr-res(1,1) res(1,1) nc-res(1,2) res(1,2)]; %upper, lower, right, left
switch min(distedges)
case distedges(1) %upper
currentwall(res(1,1)+1:nr+2, res(1,2)+1 ) = 1;
case distedges(2) %lower
currentwall(1:res(1,1)+1, res(1,2)+1) = 1;
case distedges(3); %right
currentwall(res(1,1)+1, res(1,2)+1:nc+2) = 1;
case distedges(4); %left
currentwall(res(1,1)+1, 1:res(1,2)+1) = 1;
end
res = res(2:end,:);
end
if disp == 1,
figure(4);
imagesc(currentwall);
colorbar
axis xy
title('Branch cuts')
colormap gray
drawnow
end
%% Safe unwrap from start position (this could be made faster)
% Only defined the maximum square, could be made faster by defining a
% rectangle for example
[wallposy wallposx] = find(currentwall == 1); % finds wall positions
%distnearest = (wallposy-nrstart).^2+(wallposx-ncstart).^2;
%distnearest = abs(wallposy-nrstart)+abs(wallposx-ncstart);
distnearest = max(abs(wallposy-nrstart),abs(wallposx-ncstart));
indi = find(distnearest == min(distnearest),1);
longi = min(distnearest)-2;
%longi = min([longi nrstart-1 ncstart-1 nc-ncstart-1 nr-nrstart-1]);
% figure(100);
% plot(wallposx,wallposy,'o');
% hold on,
% plot(ncstart,nrstart,'or'),
% plot([-longi longi]+ncstart,[-longi -longi]+nrstart,'-r');
% plot([-longi longi]+ncstart,[longi longi]+nrstart,'-r');
% plot([-longi -longi]+ncstart,[longi -longi]+nrstart,'-r');
% plot([longi longi]+ncstart,[longi -longi]+nrstart,'-r');
% hold off,
%%
faserecon = fase*0;
shadow = faserecon+1; % not unwrapped yet
% faserecon(nrstart,ncstart) = fase(nrstart,ncstart);
% shadow(nrstart,ncstart) = 0;
% counter = 0;
% faserecon(nrstart+[-longi:longi],ncstart+[-longi:longi]) ...
% = unwrap(unwrap( fase(nrstart+[-longi:longi],ncstart+[-longi:longi])')');
% shadow(nrstart+[-longi:longi],ncstart+[-longi:longi]) = 0;
xmask = [max(1,ncstart-longi):min(nc,ncstart+longi)];
ymask = [max(1,nrstart-longi):min(nr,nrstart+longi)];
faserecon(ymask,xmask) = unwrap(unwrap( fase(ymask,xmask)')');
shadow(ymask,xmask) = 0;
counter = 0;
% Start unwrapping
maxiter = 2*max(nr,nc);
wallvert = currentwall(1:end-1,:)&currentwall(2:end,:); % prevents horizontal integration
%wallvert = [zeros(1,nc-1);wallvert;zeros(1,nc-1)];
wallhor = currentwall(:,1:end-1)&currentwall(:,2:end); % prevents horizontal integration
%wallhor = [zeros(nr-1,1) wallhor zeros(nr-1,1)];
while (counter <maxiter)&&(max(shadow(:))==1);
shadowprev = shadow;
%%%%% Step right
%newrec = [zeros(nr,1) shadow(:,2:end)-shadow(:,1:end-1)] == 1;
newrec = [false(nr,1) shadow(:,2:end)&not(shadow(:,1:end-1))];
%prev = [zeros(nr,1) shadow(:,2:end)-shadow(:,1:end-1)] == -1;
% Block forbiden paths here
newrec(:,2:end) = newrec(:,2:end)&(1-wallvert(1:end-1,2:end-2));
deltafase = [zeros(nr,1) fase(:,2:end)-faserecon(:,1:end-1)].*newrec;
%faserecon = faserecon + (fase - round(deltafase/(2*pi))*2*pi).*newrec;
faserecon(newrec) = fase(newrec) - round(deltafase(newrec)/(2*pi))*2*pi;
shadow(newrec) = 0;
%%%%% Step left
%newrec = [shadow(:,1:end-1)-shadow(:,2:end) zeros(nr,1)] == 1;
newrec = [shadow(:,1:end-1)&not(shadow(:,2:end)) false(nr,1)];
%prev = [zeros(nr,1) shadow(:,2:end)-shadow(:,1:end-1)] == -1;
% Block forbiden paths here
newrec(:,1:end-1) = newrec(:,1:end-1)&(1-wallvert(1:end-1,2:end-2));
deltafase = [fase(:,1:end-1)-faserecon(:,2:end) zeros(nr,1)].*newrec;
%faserecon = faserecon + (fase - round(deltafase/(2*pi))*2*pi).*newrec;
faserecon(newrec) = fase(newrec) - round(deltafase(newrec)/(2*pi))*2*pi;
shadow(newrec) = 0;
%%%%% Step up (positive y)
%newrec = [zeros(1,nc) ; shadow(2:end,:)-shadow(1:end-1,:)] == 1;
newrec = [false(1,nc) ; shadow(2:end,:)&not(shadow(1:end-1,:))];
%prev = [zeros(nr,1) shadow(:,2:end)-shadow(:,1:end-1)] == -1;
% Block forbiden paths here
newrec(2:end,:) = newrec(2:end,:)&(1-wallhor(2:end-2,1:end-1));
deltafase = [zeros(1,nc) ; fase(2:end,:)-faserecon(1:end-1,:)].*newrec;
%faserecon = faserecon + (fase - round(deltafase/(2*pi))*2*pi).*newrec;
faserecon(newrec) = fase(newrec) - round(deltafase(newrec)/(2*pi))*2*pi;
shadow(newrec) = 0;
%%%%% Step down (negative y)
%newrec = [shadow(1:end-1,:)-shadow(2:end,:) ; zeros(1,nc)] == 1;
newrec = [shadow(1:end-1,:)&not(shadow(2:end,:)) ; false(1,nc)];% Logical input does not seeem to help with computing time
%prev = [zeros(nr,1) shadow(:,2:end)-shadow(:,1:end-1)] == -1;
% Block forbiden paths here
newrec(1:end-1,:) = newrec(1:end-1,:)&(1-wallhor(2:end-2,1:end-1));
deltafase = [fase(1:end-1,:)-faserecon(2:end,:) ; zeros(1,nc)].*newrec;
%faserecon = faserecon + (fase - round(deltafase/(2*pi))*2*pi).*newrec;
faserecon(newrec) = fase(newrec) - round(deltafase(newrec)/(2*pi))*2*pi;
shadow(newrec) = 0;
counter = counter+1;
if any(not(shadow(:)==shadowprev(:))) == 0,
warning('Not all points are accessible for integration')
faserecon(shadow==1) = fase(shadow==1);
break;
end
if disp == 1,
figure(5);
imagesc(faserecon);
colorbar
axis xy
title('Reconstructed phase')
colormap jet
drawnow;
end
end
if counter == maxiter,
warning('Maximum number of iterations exceeded for unwrapping. Increase maxiter.'),
end