(注意)
ここで公開しているソースコードは自由に改変・再配布してかまいませんが、
内容について作者は一切の責任を負いません。
(1) ファイル mom_inv.zip
をダウンロードして適当なフォルダに展開してください。
(2) [4]のサイトの"MATLABコード"からファイルをダウンロードして適当なフォルダに展開し、
この中から3個の数値ファントムのファイル
(mediumLabelList_Reso1mm_Case1.txt~mediumLabelList_Reso1mm_Case3.txt)
を(1)のフォルダにコピーしてください。
(3) MATLABを起動してエディターウィンドウに(1)のフォルダの
"mom_inv.m"と"input_parameter.m" を開いてください。
(必要に応じて他のファイルも開いてください)
以上でプログラムを実行する環境が整います。
計算を実行する前に、リスト7.1のようにinput_parameter.mの入力データを編集してください。
リスト7.1は表5-2のNo.4の状態です。
リスト7-1 入力データの編集(input_parameter.mの一部)
1 %% input parameters
2 function [Parm, Na, Nf] = input_parameter()
3 %%
4 Parm.restart = 0; % restart (0/1)
5 Parm.H = 8; % ボクセル合体数(整数)
6
7 % 計算条件
8 Parm.maxit = 100; % 最大反復回数
9 Parm.tol = 1e-4; % 収束判定条件
10 Parm.alpha = 0.01; % 正則化パラメータα
11 Parm.c0 = 3.0; % コントラスト初期値c0
12
13 % アンテナ
14 ra = 60e-3; % アンテナ面と原点の距離[m]
15 nxa = 4; % X方向アンテナ数
16 nya = 4; % Y方向アンテナ数
17 nza = 3; % Z方向アンテナ数
18
19 % (1)周囲 (2)脂肪 (3)乳腺 (4)カップ (5)がん (6)皮膚
20 %Parm.epsr = [6.2 7.0 35.0 9.4 50.0 35.0 ];
21 %Parm.sigm = [0.15 0.21 1.05 0 1.5 1.05];
22 Parm.epsr = [5.0 6.5 40.0 9.4 54.0 40.0];
23 Parm.sigm = [0.1 0.2 1.0 0 1.3 1.0];
24 Parm.epsr(1) = Parm.epsr(2); % background=fat
25 Parm.sigm(1) = Parm.sigm(2);
26 Parm.epsr(4) = Parm.epsr(2); % cup=fat
27 Parm.sigm(4) = Parm.sigm(2);
28
29 % 周波数
30 freq = 2.0e9; % 1周波数のとき
31 %freq = linspace(2.0e9, 2.2e9, 2); % 複数周波数のとき
32 Nf = length(freq);
計算を実行するには、コマンドウィンドウで "mom_inv" と実行してください。
コマンドウィンドウに計算経過が表示され、同時に図形出力が行われます。
図形出力はfigure1~figure6から成ります。
それらはファイル "mom_inv.m" のコメントでON/OFFにすることができます。
それぞれの内容は以下の通りです。
本シミュレーターはリスタート機能を持っています。
リスト7-1の4行目を"1"として再度実行します。
これは以下の用途に使用します。
(リスタートが終了したら4行目は"0"に戻してください)
リスト7-2 主プログラムのソースコード(mom_inv.m)
1 %{
2 mom_inv.m (chapter 5_2_1)
3 %}
4
5 clearvars;
6 %close all;
7 tic;
8
9 % input parameters
10 [Parm, Na, Nf] = input_parameter();
11 %figure1(Parm, Na); shg;
12
13 % read numerical phantom
14 medLabFile = 'mediumLabelList_Reso1mm_Case1.txt';
15 [Parm, Epsr, Sigm] = read_phantom(medLabFile, Parm);
16 if Parm.err
17 return;
18 end
19
20 % setup
21 [Parm, N, T10, T20, Robj, Iobj] = setup(Parm, Epsr, Sigm);
22 strtitle = sprintf('H=%d, N=%d, 3N=%d, Na=%d, Na^2=%d, Nf=%d, α=%g, c0=%g', Parm.H, N, 3 * N, Na, Na^2, Nf, Parm.alpha, Parm.c0);
23 fprintf("%s\n", strtitle);
24 I = eye(3 * N);
25
26 % green's function
27 % G : 3N x 3N x Nf
28 % Ga : Na x 3N x Nf
29 [G, Ga] = green(Parm, N, Na, Nf, Robj);
30
31 % E-inc
32 Ei = einc(Parm, N, Na, Nf, Robj); % 3N x Na x Nf
33
34 % forward calculation
35 if (Parm.restart == 0)
36 % solve E
37 E_fwd = zeros(Na^2, Nf);
38 for ifreq = 1 : Nf
39 tau = T10 + (T20 * Parm.joe(ifreq)); % 1 x N
40 S = diag([tau; tau; tau]); % 3N x 3N
41 [Et, E_fwd(:, ifreq)] = solve(ifreq, N, Na, S, G, Ga, Ei);
42 %figure2(Parm, N, Iobj, Et); shg;
43 end
44
45 % initial value for iteration
46 T1 = zeros(N, 1);
47 T2 = zeros(N, 1);
48 for n = 1 : N
49 T1(n) = Parm.c0 * 0.03;
50 T2(n) = Parm.c0;
51 end
52 elseif (Parm.restart == 1)
53 % restart : load
54 load 'mom_inv.mat' E_fwd T1 T2
55 end
56
57 % backward calculation (iteration)
58 fprintf('iter dE/E dεr/εr dσ/σ (εr-εr0)/εr0 (σ-σ0)/σ0 g\n');
59 fiter = [];
60 for iter = 1 : Parm.maxit
61 sumf = zeros(1, 6);
62 for ifreq = 1 : Nf
63 % solve E
64 % Et : 3N x Na
65 % E_bwd : Na^2 x 1
66 % S : 3N x 3N
67 tau = T1 + (T2 * Parm.joe(ifreq));
68 S = diag([tau; tau; tau]);
69 [Et, E_bwd] = solve(ifreq, N, Na, S, G, Ga, Ei);
70
71 % dE : Na^2 x 1
72 dE = E_bwd - E_fwd(:, ifreq);
73
74 % matrix D
75 D = zeros(Na^2, 3 * N); % Na^2 x 3N
76 invISG = inv(I - S * G(:, :, ifreq)); % 3N x 3N
77 for ir = 1 : Na
78 D((ir - 1) * Na + 1 : ir * Na, :) = Ga(:, :, ifreq) * invISG * diag(Et(:, ir)); % Na x 3N
79 end
80
81 % g : regularization factor
82 tr = trace(D' * D);
83 eerr = norm(dE) / norm(E_bwd);
84 g = Parm.alpha * tr / (3 * N) * eerr^2;
85
86 % update T
87 dm = (D' * D + g * I) \ D'; % 3N x Na^2
88 dS = dm * dE; % 3N x 1
89 dS = reshape(dS, N, 3); % N x 3
90 dT = (dS(:, 1) + dS(:, 2) + dS(:, 3)) / 3;
91 T1 = T1 - real(dT);
92 T2 = T2 - imag(dT) / Parm.oe(ifreq);
93
94 % correct T
95 [T1, T2] = correct(T1, T2, Parm);
96
97 % monitor
98 sumf(1) = sumf(1) + eerr;
99 sumf(2) = sumf(2) + norm(imag(dT)) / norm(T2) / Parm.oe(ifreq);
100 sumf(3) = sumf(3) + norm(real(dT)) / norm(T1);
101 sumf(4) = sumf(4) + norm(T2 - T20) / norm(T20);
102 sumf(5) = sumf(5) + norm(T1 - T10) / norm(T10);
103 sumf(6) = sumf(6) + g;
104 end
105 sumf = sumf / Nf;
106
107 % monitor
108 if (iter == 1)
109 fid = fopen('mom_inv.log', 'wt');
110 end
111 fprintf( '%3d %e %e %e %e %e %e\n', iter, sumf);
112 fprintf(fid, '%3d %e %e %e %e %e %e\n', iter, sumf);
113
114 % plot iteration
115 fiter = figure3(strtitle, fiter, sumf); shg;
116 figure4(Parm, N, T10, T20, T1, T2); shg;
117
118 % check convergence
119 if (sumf(2) < Parm.tol) && (sumf(3) < Parm.tol)
120 break;
121 end
122 end
123
124 % plot epsr/sigma contour and histogram
125 figure5(Parm, N, T1, T2, Iobj, Epsr, Sigm);
126 figure6(Parm, T1, T2);
127
128 % output
129 save 'mom_inv.mat' E_fwd T1 T2
130
131 toc
132 %end
133
134 %% solve E
135 function [Et, Es] = solve(ifreq, N, Na, S, G, Ga, Ei)
136 %%
137 I = eye(3 * N);
138 igs = I - G(:, :, ifreq) * S; % 3N x 3N
139 Et = igs \ Ei(:, :, ifreq); % 3N x Na
140 es = Ga(:, :, ifreq) * S * Et; % Na x Na
141 Es = reshape(es, Na^2, 1); % Na^2 x 1
142 end
143
144 %% correct T
145 function [T1, T2] = correct(T1, T2, Parm)
146 %%
147 sgm0 = T1 + Parm.sigm(1);
148 eps0 = T2 + Parm.epsr(1);
149 eps1 = max(1, min(60, eps0));
150 sgm1 = max(0.02 * eps1, min(0.04 * eps1, sgm0));
151 T1 = sgm1 - Parm.sigm(1);
152 T2 = eps1 - Parm.epsr(1);
153 end