├── .gitignore ├── LICENSE ├── README.md ├── ef.m ├── er.m ├── findpeaks2.m ├── ghio2d.m ├── gshrinkwrap.m ├── hio2d.m ├── hio3d.m ├── hiosupport.m ├── myalign.m └── shrinkwrap.m /.gitignore: -------------------------------------------------------------------------------- 1 | *.asv 2 | *.m~ 3 | README.html 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Po-Nan Li 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ghio-matlab 2 | =========== 3 | 4 | Guided hybrid input-and-output (GHIO), HIO and shrink-wrap Matlab functions 5 | 6 | # Introduction 7 | 8 | This Matlab function set consists of some useful functions for phase retrival and image reconstruction that widely used in the community of X-ray coherent diffraction imaging (XCDI). 9 | 10 | # Function usage 11 | 12 | ## hio2d.m 13 | Developed by Fienup [1], well known and widely used algorithm for XCDI resarch.Supports oversampling smoothness develped by Miao's group [2]. 14 | 15 | ### Syntax 16 | ``` 17 | function R = hio2d(Fabs, S, n) 18 | function R = hio2d(Fabs, S, n, ukwn, alpha) 19 | ``` 20 | 21 | ## ghio.m 22 | Developed by Chien-Chun Chen *et al*. when he was in Institute of Physics in Academia Sinica [3]. 23 | 24 | ### Syntax 25 | ``` 26 | function R = ghio2d(Fabs, S, n, gen, rep, checker, alpha) 27 | function [R, G, efs] = ghio2d(Fabs, S, n, gen, rep, checker, alpha) 28 | ``` 29 | 30 | 31 | ## shrinkwrap.m 32 | Developed by S. Marchesini *et al*. [4]. 33 | 34 | ### Syntax 35 | ``` 36 | gshrinkwrap(Fabs, n1, uknwn, gen, n2); 37 | gshrinkwrap(Fabs, n1, ukwn, gen, n2, alpha); 38 | gshrinkwrap(Fabs, n1, ukwn, gen, n2, alpha, sigma, cutoff1, cutoff2); 39 | ``` 40 | 41 | ### Description 42 | 43 | 44 | ## gshrinkwrap.m 45 | 46 | ### Syntax 47 | ``` 48 | gshrinkwrap(Fabs, n1, uknwn, gen, n2, rep); 49 | gshrinkwrap(Fabs, n1, ukwn, gen, n2, rep, alpha); 50 | gshrinkwrap(Fabs, n1, ukwn, gen, n2, rep, alpha, sigma, cutoff1, cutoff2); 51 | ``` 52 | 53 | 54 | # References 55 | 56 | [1] J.R. Fienup, Appl. Opt. **21**, 2758 (1982). 57 | 58 | [2] J.A. Rodriguez *et al*., J. Appl. Cryst. **46** (2013). 59 | 60 | [3] C.-C. Chen *et al*., Phys. Rev. B **59**, 064113 (2007). 61 | 62 | [4] S. Marchesini *et al*., Phys. Rev. B **68**, 140101 (2003). 63 | -------------------------------------------------------------------------------- /ef.m: -------------------------------------------------------------------------------- 1 | function err = ef(Fabs, F, checker) 2 | err = sum(sum( abs( abs(Fabs(~checker)) - abs(F(~checker)) ) )); 3 | err = err ./ sum(sum( abs(Fabs(~checker)) )); 4 | end -------------------------------------------------------------------------------- /er.m: -------------------------------------------------------------------------------- 1 | function err = er(A,R,S) 2 | if numel(S) > 0 3 | err = sum(sum( abs( abs(A(S)) - abs(R(S)) ) )); 4 | err = err ./ sum(sum( abs(A(S)) )); 5 | else 6 | err = sum(sum( abs( abs(A) - abs(R) ) )); 7 | err = err ./ sum(sum( abs(A) )); 8 | end 9 | 10 | end -------------------------------------------------------------------------------- /findpeaks2.m: -------------------------------------------------------------------------------- 1 | function [r, c, y] = findpeaks2(data) 2 | [h w] = size(data); 3 | r = 0; 4 | c = 0; 5 | y = -inf; 6 | t = 1; 7 | for u = 2:(h-1) 8 | for v = 2:(w-1) 9 | if (data(u,v) > data(u+1,v)) && (data(u,v) > data(u,v+1)) && (data(u,v) > data(u-1,v)) && (data(u,v) > data(u,v-1)) 10 | r(t) = u; 11 | c(t) = v; 12 | y(t) = data(u,v); 13 | t = t+1; 14 | end 15 | end 16 | end 17 | 18 | [y, si] = sort(y,'descend'); 19 | r = r(si); 20 | c = c(si); 21 | 22 | end -------------------------------------------------------------------------------- /ghio2d.m: -------------------------------------------------------------------------------- 1 | % 2-D Guided-HIO written by Po-Nan Li @ Academia Sinica 2012 2 | % Reference: Chen et al., Phys. Rev. B. 76, 064113 (2007). 3 | function [R, G, efs] = ghio2d(Fabs, S, n, gen, rep, checker, alpha) 4 | R = zeros(size(Fabs,1), size(Fabs,2), gen); 5 | G = zeros(size(Fabs,1), size(Fabs,2), rep); 6 | FG = zeros(size(Fabs,1), size(Fabs,2), rep); 7 | efs = zeros(gen, rep); 8 | sh = floor(sqrt(numel(find(S==1)))/2); % maximun shift 9 | GM = zeros(size(Fabs)); 10 | 11 | for g = 1:gen 12 | disp(['in generation #' int2str(g)]); 13 | if g == 1 14 | parfor r = 1:rep 15 | G(:,:,r) = hio2d(Fabs, S, n, checker, alpha); 16 | % additional treat to FG 17 | FG(:,:,r) = G(:,:,r); 18 | FG(:,:,r) = FG(:,:,r) .* S; 19 | FG(:,:,r) = fft2( FG(:,:,r) ); 20 | efs(g,r) = ef(Fabs, FG(:,:,r), checker); 21 | end 22 | else 23 | parfor r = 1:rep 24 | % make new template 25 | G(:,:,r) = myalign( GM, G(:,:,r) ); 26 | G(:,:,r) = sign( G(:,:,r) ) .* sqrt( abs(G(:,:,r) .* GM) ); 27 | % run independent HIO 28 | G(:,:,r) = hio2d(fft2(G(:,:,r)), S, n, checker, alpha); 29 | % additional treat to FG 30 | FG(:,:,r) = G(:,:,r); 31 | FG(:,:,r) = FG(:,:,r) .* S; 32 | FG(:,:,r) = fft2( FG(:,:,r) ); 33 | efs(g,r) = ef(Fabs, FG(:,:,r), checker); 34 | end 35 | end 36 | % find the best replica 37 | [min_ef, min_ind] = min(efs(g,:)); 38 | disp(['replica #' int2str(min_ind) ' selected (EF = ' num2str(min_ef) ')']); 39 | GM = G(:,:,min_ind); 40 | R(:,:,g) = GM; 41 | disp('==========================================================='); 42 | end 43 | 44 | 45 | 46 | end -------------------------------------------------------------------------------- /gshrinkwrap.m: -------------------------------------------------------------------------------- 1 | % [R, Sup, M] = gshrinkwrap(Fabs, n, checker, gen, n2, rep, varargin) 2 | % varargin = {alpha, sigma, cutoff1, cutoff2} 3 | % GUIDED shrink-wrap 2-D HIO written by Po-Nan Li @ Academia Sinica 2014 4 | % reference: 5 | % [1] Marchesini et al., 6 | % "X-ray image reconstruction from a diffraction pattern alone," 7 | % Phys. Rev. B 68, 140101 (2003). 8 | % [2] Chen et al., Phys. Rev. B 76, 064113 (2007). 9 | % 10 | % v.1 2014/06/03 : multiple seed 11 | % v.2 2014/06/06 : multiple following runs 12 | % v.3 2014/06/09 : use "template" to update each replica 13 | 14 | function [R, Sup, Rtmp, efs] = gshrinkwrap(Fabs, n, checker, gen, n2, rep, varargin) 15 | 16 | 17 | % default parameters; 18 | alpha = []; 19 | sig = 3; 20 | cutoff1 = 0.04; 21 | cutoff2 = 0.2; 22 | 23 | 24 | % handle additional aruguments 25 | if ~isempty(varargin) 26 | alpha = varargin{1}; 27 | if length(varargin) > 1 28 | sig = varargin{2}; 29 | if length(varargin) > 2 30 | cutoff1 = varargin{3}; 31 | if length(varargin) > 3 32 | cutoff2 = varargin{4}; 33 | end 34 | end 35 | end 36 | end 37 | 38 | S = fftshift( ifft2(abs(Fabs).^2, 'symmetric') ); 39 | S = S > cutoff1*max(S(:)); 40 | 41 | % pre-allocated spaces 42 | R = zeros( size(Fabs, 1), size(Fabs, 2), gen+1); 43 | Sup = false( size(Fabs, 1), size(Fabs, 2), gen+1); 44 | Sup(:,:,1) = S; 45 | 46 | % pre-allocated spaces for parallel 47 | Rtmp = zeros( size(Fabs, 1), size(Fabs, 2), rep); 48 | Ftmp = zeros( size(Fabs, 1), size(Fabs, 2), rep); 49 | Mtmp = zeros( size(Fabs, 1), size(Fabs, 2), rep); 50 | Stmp = false( size(Fabs, 1), size(Fabs, 2), rep); 51 | efs = zeros(gen+1, rep); 52 | 53 | 54 | % first run with initial support from auto-correlation map 55 | parfor r = 1:rep 56 | Rtmp(:,:,r) = hio2d(Fabs, S, n, checker, alpha); 57 | Ftmp(:,:,r) = fft2( Rtmp(:,:,r) ); 58 | efs(1,r) = ef(Fabs, Ftmp(:,:,r), checker), 59 | end 60 | 61 | % select best replica 62 | [my, mx] = min(efs(1,:)); 63 | disp('seed:'); 64 | disp(['replica #' int2str(mx) ' with EF = ' num2str(my) ' selected']); 65 | R(:,:,1) = Rtmp(:,:,mx); 66 | 67 | % make Gaussian kernel 68 | x = (1:size(S,2)) - ceil(size(S,2)/2) - 1; 69 | y = (1:size(S,1)) - ceil(size(S,1)/2) - 1; 70 | [X, Y] = meshgrid(x, y); 71 | rad = sqrt(X.^2 + Y.^2); 72 | 73 | 74 | % shrink-wrap 75 | for g = 2:(gen+1) 76 | Rmodel = R(:,:,g-1); 77 | % Rmodel( Rmodel < 0 ) = 0; % just in case 78 | % Rtmp( Rtmp < 0 ) = 0; 79 | 80 | parfor r = 1:rep 81 | % real-space improvement 82 | Rtmp(:,:,r) = myalign( Rmodel, Rtmp(:,:,r) ); 83 | Rtmp(:,:,r) = sign( Rtmp(:,:,r) )... 84 | .* sqrt( abs( Rtmp(:,:,r) .* Rmodel ) ); 85 | G = fft2(exp(-(rad./sqrt(2)./sig).^2)); 86 | % make new support 87 | Mtmp(:,:,r) = fftshift( ifft2( fft2(Rtmp(:,:,r)) .* G, 'symmetric') ); 88 | Stmp(:,:,r) = ( Mtmp(:,:,r) >= cutoff2*max(max(Mtmp(:,:,r))) ); 89 | % run hio 90 | Rtmp(:,:,r) = hio2d(fft2(Rtmp(:,:,r)), Stmp(:,:,r), n2, checker, alpha); 91 | % Fourier transform for EF 92 | Ftmp(:,:,r) = Rtmp(:,:,r) .* Stmp(:,:,r); 93 | Ftmp(:,:,r) = fft2( Rtmp(:,:,r) ); 94 | efs(g,r) = ef(Fabs, Ftmp(:,:,r), checker), 95 | end 96 | % EF analysis 97 | [my, mx] = min(efs(g,:)); 98 | disp(['after generation ' int2str(g) ':']); 99 | disp(['replica #' int2str(mx) ' with EF = ' num2str(my) ' selected']); 100 | R(:,:,g) = Rtmp(:,:,mx); 101 | Sup(:,:,g) = Stmp(:,:,mx); 102 | % smaller the kernel size 103 | if sig > 1.5 104 | sig = sig * 0.99; 105 | end 106 | end 107 | 108 | 109 | -------------------------------------------------------------------------------- /hio2d.m: -------------------------------------------------------------------------------- 1 | % 2-D HIO written by Po-Nan Li @ Academia Sinica 2012 2 | function R = hio2d(Fabs, S, n, varargin) % Fabs, S, n, unknown, alpha 3 | 4 | 5 | if isempty(varargin) 6 | unknown = false(size(Fabs)); 7 | else 8 | unknown = varargin{1}; 9 | end 10 | % OSS module 11 | if length(varargin) > 1 && ~isempty( varargin{2} ) 12 | alpha = varargin{2}; 13 | disp(['OSS is on. alpha = ' num2str(alpha)]); 14 | oss = true; 15 | x = -round((length(Fabs)-1)/2):round((length(Fabs)-1)/2); 16 | [X, Y] = meshgrid(x, x); 17 | W = exp(-0.5 .* (X./alpha).^2) .* exp(-0.5 .* (Y./alpha).^2); 18 | W = ifftshift(W); 19 | else 20 | oss = false; 21 | end 22 | % solve unknown pixels in data 23 | 24 | 25 | beta1 = 0.9; 26 | 27 | % generate random initial phases 28 | if sum(imag(Fabs(:))) == 0 29 | ph_init = rand(size(Fabs)); 30 | ph_init = angle(fft2(ph_init)); 31 | F = Fabs .* exp(1j.*ph_init); 32 | else 33 | F = Fabs; 34 | end 35 | 36 | F0 = abs(F); 37 | previous = ifft2(F, 'symmetric'); 38 | 39 | % ================ iterations ================================== 40 | for t = 1:n 41 | if mod(t-1, 100) == 0 && n >= 500 42 | disp(['step ' int2str(t)]); 43 | end 44 | rs = ifft2(F, 'symmetric'); % real space version 45 | cond1 = ~S | (rs<0); 46 | rs(cond1) = previous(cond1) - beta1 .* rs(cond1); 47 | previous = rs; 48 | if oss 49 | rs_oss = ifft2(fft2(rs) .* W, 'symmetric'); 50 | rs(~S) = rs_oss(~S); 51 | end 52 | F2 = fft2(rs); % .* exp(-1j.*(U+V)); 53 | F = F0 .* exp(1j.*angle(F2)); 54 | F(unknown) = F2(unknown); 55 | end 56 | % ================ iterations ends here ================================== 57 | R = ifft2(F, 'symmetric'); 58 | end -------------------------------------------------------------------------------- /hio3d.m: -------------------------------------------------------------------------------- 1 | % 3-D HIO written by Po-Nan Li @ Academia Sinica 2012 2 | function R = hio3d(Fabs, S, n, varargin) 3 | 4 | beta1 = 0.9; % feedback parameter 5 | 6 | if isempty(varargin) 7 | unknown = false(size(Fabs)); 8 | else 9 | unknown = varargin{1}; 10 | end 11 | 12 | % generate initial random phases 13 | if sum(abs(imag( Fabs(:) ))) == 0 14 | ph_init = rand(size(Fabs)); 15 | ph_init = angle(fftn(ph_init)); 16 | F = Fabs .* exp(1j*ph_init); 17 | else 18 | F = Fabs; 19 | end 20 | 21 | F0 = abs(F); 22 | previous = ifftn(F, 'symmetric'); 23 | % ================ iterations ================================== 24 | for t = 1:n 25 | if mod(t-1, 100) && n > 499 26 | disp(['step ' int2str(t)]); 27 | end 28 | 29 | rs = ifftn(F, 'symmetric'); % real space version 30 | % apply the support 31 | cond1 = ~S | (rs<0); 32 | rs(cond1) = previous(cond1) - beta1 .* rs(cond1); 33 | previous = rs; % update the buffer 34 | 35 | F2 = fftn(rs); 36 | F = F0 .* exp(1j*angle(F2)); 37 | F(unknown) = F2(unknown); 38 | end 39 | % ================ iterations ends here ================================== 40 | R = ifftn(F, 'symmetric'); 41 | end -------------------------------------------------------------------------------- /hiosupport.m: -------------------------------------------------------------------------------- 1 | function Sup = hiosupport(image_size, support_size) 2 | 3 | % image dimension 4 | img_h = image_size(1); 5 | if numel(image_size) > 1 6 | img_w = image_size(2); 7 | else 8 | img_w = image_size; 9 | end 10 | 11 | % support dimenstion 12 | sp_h = support_size(1); 13 | if numel(support_size) > 1 14 | sp_w = support_size(2); 15 | else 16 | sp_w = support_size; 17 | end 18 | 19 | 20 | 21 | Sup = false(img_h, img_w); 22 | Sup(1:sp_h, 1:sp_w) = true; 23 | 24 | Sup = circshift(Sup, [round((img_h-sp_h)/2) round((img_w-sp_w)/2)]); 25 | -------------------------------------------------------------------------------- /myalign.m: -------------------------------------------------------------------------------- 1 | function B = myalign(A, B) 2 | xcorr = fftshift( ifft2( fft2(A) .* conj(fft2(B)) ) ); 3 | [cr1, cc1, y1] = findpeaks2(xcorr); 4 | xcorr = fftshift( ifft2( fft2(A) .* conj(fft2( rot90(B,2) )) ) ); 5 | [cr2, cc2, y2] = findpeaks2(xcorr); 6 | if y2(1) > y1(1) 7 | B = rot90(B, 2); 8 | cr2 = cr2(1) - round(size(A,1)/2); 9 | cc2 = cc2(1) - round(size(A,2)/2); 10 | B = circshift(B, [cr2, cc2]); 11 | disp(['myalign: inverted and shifted (' int2str(cr2) ', ' int2str(cc2) ').']); 12 | else 13 | cr1 = cr1(1)- round(size(A,1)/2); 14 | cc1 = cc1(1) - round(size(A,2)/2); 15 | B = circshift(B, [cr1, cc1]); 16 | disp(['myalign: shifted (' int2str(cr1) ', ' int2str(cc1) ').']); 17 | end 18 | 19 | end -------------------------------------------------------------------------------- /shrinkwrap.m: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/liponan/ghio-matlab/4f5bb5d8611564872efa506bba0a1a018d9fe2d1/shrinkwrap.m --------------------------------------------------------------------------------