-
Notifications
You must be signed in to change notification settings - Fork 3
/
randgpn.m
101 lines (86 loc) · 3.24 KB
/
randgpn.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
function varargout=randgpn(k,dc,dcn,xver)
% [Zk,Zx]=randgpn(k,dc,dcn,xver)
%
% Returns a set of (complex proper) normal variables suitable for
% IFFT2, most notably this works for even and/or odd sized rectangles.
%
% INPUT:
%
% k A wavenumber matrix (DC component in center)
% dc The (m,n) indices to the DC component in k
% dcn The (m,n) indices to the Nyquist components in k
% --> Note that these three are straight out of KNUM2, and that
% the actual wavenumbers are not used, only size(k) is needed.
% xver 1 Checks the Hermiticity of the result by inverse transformation
% 0 No such check is being conducted
%
% OUTPUT:
%
% Zk A size(k) matrix with (complex proper) normal Fourier variables
% Zx A size(k) matrix with a real-valued random field
%
% EXAMPLE 1
%
% [k,kx,ky,dci,dcn]=knum2([round(rand*100) round(rand*100)],[100 100]);
% [Zk,Zx]=randgpn(k,dci,dcn); imagesc(Zx)
%
% EXAMPLE 2
%
% [k,kx,ky,dci,dcn]=knum2([200 201],[100 100]);
% F=abs(randn*10); [Zk,Zx]=randgpn(k,dci,dcn); Zf=ifft2(ifftshift(Zk.*exp(-F*k)));
% imagef([0 0],size(Zf),Zf); axis image ;
% title(sprintf('exp(%3.3gk)',-F)); colorbar('hor')
%
% SEE ALSO: KNUM2, KNUM1
%
% Last modified by fjsimons-at-alum.mit.edu, 03/18/2019
defval('xver',0)
% Make a receptacle with the dimension of the wavenumbers
[m,n]=size(k);
Zk=zeros(m,n); clear k
% Determine the parity
modd=mod(m,2);
nodd=mod(n,2);
% Define the ranges to pick out a half plane; DC is (0,0) is included
lhn=1:dc(2);
rhn=dc(2)+1:n;
% Now make some complex proper normal random variables of half variance
ReZk=randn(m,dc(2))/sqrt(2);
ImZk=randn(m,dc(2))/sqrt(2);
% And make a handful real normal random variables of unit variance
realZk=randn(4,1);
% Fill the entire left half plane with these random numbers
lh=ReZk+sqrt(-1)*ImZk;
Zk(:,lhn)=lh;
% Now overwrite and symmetrize the column containing zero
Zk(dc(1)+1:end,dc(2))=conj(flipud(Zk(2-modd:dc(1)-1,dc(2))));
% Fill the center with a real, where the DC component goes
Zk(dc(1),dc(2))=realZk(1);
% Fill the Nyquist with a real, if we capture them exactly
for ind=1:size(dcn,1)
Zk(dcn(ind,1),dcn(ind,2))=realZk(1+ind);
end
% The intersection of two columns with a Nyquist should also be real
% cos(k_x x+k_y y)+i sin(k_x x+k_y y) at (k_x,k_y)=(-pi,-pi) and for x and
% y integers, the sin term vanishes thus the cos is real and the
% multiplier must be real! And the x and y are integers because they are
% multiplying the sampling interval which factors out.
Zk(~modd,~nodd)=realZk(1+ind+1);
% And now symmetrize the right half plane so that output is Hermitian
Zk(2-modd:end,rhn)=conj(flipud(fliplr(lh(2-modd:end,2-nodd:dc(2)-1))));
% Symmetrize the top row that may contain the Nyquist, if it does
Zk(~modd,dc(2)+1:end)=conj(fliplr(Zk(~modd,2-nodd:dc(2)-1)));
% Symmetrize the leftmost column that may contain the Nyquist, if it does
Zk(dc(1)+1:end,~nodd)=conj(flipud(Zk(2-modd:dc(1)-1,~nodd)));
if nargout>1 || xver==1
Zx=ifft2(ifftshift(Zk));
% You could now check that the IFFT2 is real (don't forget the "2"!!)
if ~isreal(Zx) ; error(sprintf('Not Hermitian by %5g',mean(imag(Zx(:))))); end
% You can perform this check more directly as well
hermcheck(Zk)
else
Zx=NaN;
end
% Output
varns={Zk,Zx};
varargout=varns(1:nargout);