% 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,:)¤twall(2:end,:); % prevents horizontal integration %wallvert = [zeros(1,nc-1);wallvert;zeros(1,nc-1)]; wallhor = currentwall(:,1:end-1)¤twall(:,2:end); % prevents horizontal integration %wallhor = [zeros(nr-1,1) wallhor zeros(nr-1,1)]; while (counter