This repository has been archived by the owner on May 30, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathSENSE.m
143 lines (125 loc) · 4.44 KB
/
SENSE.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
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
%% Assignment 2-1: SENSE Reconstruction
%% SENSE
% (SENSitivity Encoding) parallel imaging reconstruction method.
%
% See <http://mriquestions.com/senseasset.html here> for a basic introduction.
% See <https://www.researchgate.net/publication/8178233_SMASH_SENSE_PILS_GRAPPA_how_to_choose_the_optimal_method
% this review paper> (p.226) for a more detailed explanation.
%
% The notation used in the code below is based on the review paper.
%% Loading data
brainCoilsData = load('brain_coil.mat');
brainCoils = brainCoilsData.brain_coil_tmp;
coilMapData = load('coil_sensitivity_map.mat');
coilMap = coilMapData.coil_map;
%%
[phaseLength, freqLength, coilNum] = size(brainCoils);
disp(size(brainCoils)); % Phases, Frequencies, Coil Number
%% Convert to Fourier Domain with 2D Fast Fourier Transform
% Remember to use fftshift and ifftshift when using the Fourier Transform.
%
% Otherwise, the k-space will not be centered properly.
fullKspace = ifftshift(fft2(fftshift(brainCoils)));
%%
% Examine raw k-space.
fullKspaceImage = rsos(fullKspace);
figure;
imagesc(fullKspaceImage, [0, 10000]);
colormap('gray');
colorbar();
%% Setting parameters for later use.
%%
downSamplingRate = 5;
%% Making the mask
% Creating a mask for the downsampling and the acs lines.
mask = zeros(size(fullKspace)); % Making a mask for the brain coils.
for line=1:phaseLength % Goes along the phase encoding axis.
if rem(line, downSamplingRate) == 0
mask(line, :, :) = 1; % Broadcasting the value of 1 to mask(i, :, :).
end
end
assert(isequal(size(mask), size(brainCoils)), 'Mask size is incorrect.')
%% Displaying mask.
% This code functions to check whether the mask has been made correctly.
%
% White lines indicate 1's. Black lines indicate 0's. All values should be
% either 0 or 1.
%
% There should be a white band in the middle, with striped lines surrounding
% it.
dispMask = mean(mask, 3);
figure;
imagesc(dispMask);
colormap('gray');
colorbar();
%% Generating the down-sampled k-space image
% Obtain the Hadamard product (elementwise matrix multiplication) between the
% full k-space data and the mask.
%
% Hint: use the .* operator, not the * operator, which does matrix multiplication.
% Elementwise (Hadamard) product (multiplication) of matrices.
downSampledKspace = fullKspace .* mask;
%% Confirmation
% Confirming that the masking has been performed properly in k-space.
downSampledKspaceImage = rsos(downSampledKspace);
figure;
imagesc(downSampledKspaceImage, [0, 10000]);
colormap('gray');
colorbar();
assert(isequal(size(downSampledKspace), size(brainCoils)), 'Reconstruction is of the wrong shape.')
%% Returning the downsampled data to image space.
%%
dsBrainCoils = ifftshift(ifft2(fftshift(downSampledKspace)));
assert(isequal(size(dsBrainCoils), size(brainCoils)), 'Image shape is wrong.');
%% Checking reconstructed image.
%%
% Using rsos (root sum of squares) to make visualization possible.
dsImage = rsos(dsBrainCoils);
figure;
imagesc(dsImage);
colormap('gray');
colorbar();
%% SENSE Reconstruction
%%
fieldOfView = floor(phaseLength/downSamplingRate); % Not a perfect solution but works for this experiment.
cHat = zeros(coilNum, downSamplingRate);
senseRecon = zeros(phaseLength, freqLength);
vectorI = zeros(coilNum, 1);
for x=1:freqLength
for y=1:fieldOfView
vectorI = reshape(dsBrainCoils(y, x, :), coilNum, 1); % All channels of single pixel in image.
for k=1:downSamplingRate
% Coil sensitivities of all channels of a single pixel per segment.
cHat(:, k) = reshape(coilMap(y+(k-1).*fieldOfView, x, :), coilNum, 1);
end
cHatPinv = pinv(cHat); % Moore-Penrose Pseudoinverse.
vectorRho = cHatPinv * vectorI;
for k=1:downSamplingRate
senseRecon(y + (k-1) .* fieldOfView, x) = vectorRho(k);
end
end
end
%% Visualizing results
%%
senseImage = rsos(senseRecon);
senseImage = senseImage .* downSamplingRate; % Necessary to correct for the missing values.
original = rsos(brainCoils);
delta = original-senseImage;
figure;
colormap('gray');
subplot(2, 2, 1);
imagesc(original);
title('Original Image');
colorbar();
subplot(2, 2, 2);
imagesc(dsImage);
title('Downsampled Image');
colorbar();
subplot(2, 2, 3);
imagesc(senseImage);
title('SENSE Image');
colorbar();
subplot(2, 2, 4);
imagesc(delta);
title('Difference Image');
colorbar();