forked from ndwork/dworkLib
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcsReconFISTA.m
More file actions
170 lines (142 loc) · 5.37 KB
/
csReconFISTA.m
File metadata and controls
170 lines (142 loc) · 5.37 KB
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
function [recon,oValues] = csReconFISTA( samples, lambda, varargin )
% recon = csReconFISTA( samples, lambda [, 'debug', debug, 'nIter', nIter, ...
% 'polish', polish, 'printEvery', printEvery, 'verbose', verbose, ...
% 'waveletType', waveletType ] )
%
% This routine minimizes 0.5 * || Ax - b ||_2^2 + lambda || W x ||_1
% where A is sampleMask * Fourier Transform * real part, and
% W is the wavelet transform.
%
% Inputs:
% samples - a 2D array that is zero wherever a sample wasn't acquired
% lambda - regularization parameter
%
% Optional Inputs:
% debug - if true, reduces the default number of iterations to 30 and forces verbose
% statements during optimization
% nIter - the number of iterations that FISTA will perform (default is 100)
% polish - if set to true, adds a polishing step (default is false)
% printEvery - FISTA prints a verbose statement every printEvery iterations
% verbose - if true, prints informative statements
% waveletType - either 'Deaubechies' for Deaubechies-4 (default) or 'Haar'
%
% Written by Nicholas Dwork - Copyright 2017
%
% https://github.com/ndwork/dworkLib.git
%
% This software is offered under the GNU General Public License 3.0. It
% is offered without any warranty expressed or implied, including the
% implied warranties of merchantability or fitness for a particular purpose.
wavSplit = zeros(4); wavSplit(1,1) = 1;
%wavSplit = [1 0 0 0; 0 0 0 0; 0 0 0 0; 0 0 0 0;];
%wavSplit = [ 1 0; 0 0; ];
p = inputParser;
p.addParameter( 'checkAdjoints', false, @islogical );
p.addParameter( 'debug', false, @(x) isnumeric(x) || islogical(x) );
p.addParameter( 'nIter', [], @ispositive );
p.addParameter( 'polish', false, @(x) isnumeric(x) || islogical(x) );
p.addParameter( 'printEvery', 1, @ispositive );
p.addParameter( 'wavSplit', wavSplit, @isnumeric );
p.addParameter( 'verbose', false, @(x) isnumeric(x) || islogical(x) );
p.addParameter( 'waveletType', 'Deaubechies', @(x) true );
p.parse( varargin{:} );
checkAdjoints = p.Results.checkAdjoints;
debug = p.Results.debug;
nIter = p.Results.nIter;
polish = p.Results.polish;
printEvery = p.Results.printEvery;
waveletType = p.Results.waveletType;
verbose = p.Results.verbose;
if numel( nIter ) == 0
if debug == true
nIter = 30;
else
nIter = 100;
end
end
nSamples = numel( samples );
M = ( samples ~= 0 );
% RI = [ Re; Im; ]
% A = M F RI , A' = (RI)' * F' * M
% A' * A = (RI)' * F' * M * F * RI
% gGrad = A'*A*x - A'*b;
function Fx = F( x )
Fx = 1/sqrt(nSamples) .* fftc( x );
end
function Fadjy = Fadj( y )
Fadjy = sqrt(nSamples) * ifftc( y );
end
function out = A( x )
Fx = F( x );
out = Fx( M == 1 );
end
function out = Aadj( y )
MTy = zeros( size( samples ) );
MTy( M==1 ) = y;
out = Fadj( MTy );
end
if checkAdjoints == true
% Variable used during debugging of this routine
checkResult = csReconFISTA_checkAdjoints( samples, @F, @Fadj, @A, @Aadj );
if checkResult ~= false, disp( 'Adjoints test passed' ); end
end
b = samples( M == 1 );
function out = g( x )
diff = A( x ) - b;
out = 0.5 * norm( diff(:), 2 ).^2;
end
Aadjb = Aadj( b );
function out = gGrad( x )
out = Aadj( A( x ) ) - Aadjb;
end
if strcmp( waveletType, 'Deaubechies' )
W = @(x) wtDeaubechies2( x, wavSplit );
WT = @(y) iwtDeaubechies2( y, wavSplit );
elseif strcmp( waveletType, 'Haar' )
W = @(x) wtHaar2( x, wavSplit );
WT = @(y) iwtHaar2( y, wavSplit );
else
error( 'Unrecognized wavelet type' );
end
proxth = @(x,t) WT( proxL1Complex( W(x), t*lambda ) );
% The proximal operator of || W x ||_1 was determined using
% Vandenberghe's notes from EE 236C; slide of "The proximal mapping" entitled
% "Composition with Affine Mapping"
function out = h( x )
Wx = W(x);
out = sum( abs( Wx(:) ) );
end
x0 = ifftc( samples ); % Could possibly make this better with inverse gridding
t = 1 / numel( samples );
if debug
%[recon,oValues] = fista( x0, @g, @gGrad, proxth, 'h', @h, 'verbose', verbose ); %#ok<ASGLU>
[recon,oValues] = fista_wLS( x0, @g, @gGrad, proxth, 'h', @h, ...
't0', t, 'N', nIter, 'verbose', true, 'printEvery', printEvery ); %#ok<ASGLU>
else
%recon = fista( x0, @g, @gGrad, proxth ); %#ok<UNRCH>
recon = fista_wLS( x0, @g, @gGrad, proxth, 't0', t, 'N', nIter, ...
'verbose', verbose, 'printEvery', printEvery );
end
if polish
maskW = proxL1Complex( W(recon), t*lambda ) ~= 0;
proxth = @(x,t) WT( maskW .* W(x) );
if debug
[recon,oValues2] = fista_wLS( recon, @g, gGrad, proxth, 'h', @h, ...
'N', nIter, 't0', t, 'verbose', verbose, 'printEvery', printEvery ); %#ok<ASGLU>
else
recon = fista_wLS( recon, @g, gGrad, proxth, 'h', @h, 'N', nIter, 't0', t, ...
'verbose', verbose, 'printEvery', printEvery );
end
end
end
function out = csReconFISTA_checkAdjoints( samples, F, Fadj, A, Aadj )
% Check to make sure that Fadj is the adjoint of F
randSamples = rand( size(samples) ) + 1i * rand( size(samples) );
if checkAdjoint( randSamples, F, Fadj ) ~= true
error( 'Fadj is not the transpose of F' );
end
if checkAdjoint( randSamples, A, Aadj ) ~= true
error( 'Aadj is not the transpose of A' );
end
out = true;
end