Commit a47d89cc authored by Mark Chiew's avatar Mark Chiew
Browse files

Made MATLAB consistent with python, added plotting to partial fourier

parent 6e5f1b9a
...@@ -18,7 +18,7 @@ subplot(2,1,2); ...@@ -18,7 +18,7 @@ subplot(2,1,2);
plot(pulseq(:,3)); plot(pulseq(:,3));
ylabel('Gradient'); ylabel('Gradient');
% Integrate ODE %% Integrate ODE
T1 = 1500; T1 = 1500;
T2 = 50; T2 = 50;
t0 = 0; t0 = 0;
...@@ -27,20 +27,20 @@ dt = 0.005; ...@@ -27,20 +27,20 @@ dt = 0.005;
M0 = [0; 0; 1]; M0 = [0; 0; 1];
[t, M] = ode45(@(t,M)bloch_ode(t, M, T1, T2), linspace(t0, t1, (t1-t0)/dt), M0); [t, M] = ode45(@(t,M)bloch_ode(t, M, T1, T2), linspace(t0, t1, (t1-t0)/dt), M0);
% Plot Results %% Plot Results
% create figure % create figure
figure();hold on; figure();hold on;
% plot x, y and z components of Magnetisation % plot x, y and z components of Magnetisation
plot(t, M(:,1)); plot(t, M(:,1), 'linewidth', 2);
plot(t, M(:,2)); plot(t, M(:,2), 'linewidth', 2);
plot(t, M(:,3)); plot(t, M(:,3), 'linewidth', 2);
% add legend and grid % add legend and grid
legend({'Mx','My','Mz'}); legend({'Mx','My','Mz'});
grid on; grid on;
% define the bloch equation %% define the bloch equation
function dM = bloch_ode(t, M, T1, T2) function dM = bloch_ode(t, M, T1, T2)
% get effective B-field at time t % get effective B-field at time t
B = B_eff(t); B = B_eff(t);
...@@ -51,7 +51,7 @@ function dM = bloch_ode(t, M, T1, T2) ...@@ -51,7 +51,7 @@ function dM = bloch_ode(t, M, T1, T2)
M(1)*B(2) - M(2)*B(1) - (M(3)-1)/T1]; M(1)*B(2) - M(2)*B(1) - (M(3)-1)/T1];
end end
% define effective B-field %% define effective B-field
function b = B_eff(t) function b = B_eff(t)
% Do nothing for 0.25 ms % Do nothing for 0.25 ms
if t < 0.25 if t < 0.25
......
...@@ -48,10 +48,11 @@ ...@@ -48,10 +48,11 @@
In this section: In this section:
- np.random.randn - np.random.randn
- np.fft - np.fft
- 0-based indexing - 0-based indexing
- image plotting
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# generate normally-distributed complex noise # generate normally-distributed complex noise
...@@ -60,10 +61,14 @@ ...@@ -60,10 +61,14 @@
# Fourier transform the image and add noise # Fourier transform the image and add noise
y = np.fft.fftshift(np.fft.fft2(img), axes=0) + n y = np.fft.fftshift(np.fft.fft2(img), axes=0) + n
# set bottom 24/96 lines to 0 # set bottom 24/96 lines to 0
y[72:,:] = 0 y[72:,:] = 0
# show sampling
_, ax = plt.subplots()
ax.imshow(np.log(np.abs(np.fft.fftshift(y, axes=1))))
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# Estimate phase # Estimate phase
...@@ -74,10 +79,11 @@ ...@@ -74,10 +79,11 @@
In this section: In this section:
- np.pad - np.pad
- np.hanning - np.hanning
- reshaping 1D array to 2D array using np.newaxis (or None) - reshaping 1D array to 2D array using np.newaxis (or None)
- subplots with titles
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
# create zero-padded hanning filter for ky-filtering # create zero-padded hanning filter for ky-filtering
...@@ -91,10 +97,17 @@ ...@@ -91,10 +97,17 @@
# generate low-res image with inverse Fourier transform # generate low-res image with inverse Fourier transform
low = np.fft.ifft2(np.fft.ifftshift(y*filt, axes=0)) low = np.fft.ifft2(np.fft.ifftshift(y*filt, axes=0))
# get phase image # get phase image
phs = np.exp(1j*np.angle(low)) phs = np.exp(1j*np.angle(low))
# show phase estimate alongside true phase
_, ax = plt.subplots(1,2)
ax[0].imshow(np.angle(img))
ax[0].set_title('True image phase')
ax[1].imshow(np.angle(phs))
ax[1].set_title('Estimated phase')
``` ```
%% Cell type:markdown id: tags: %% Cell type:markdown id: tags:
# POCS reconstruction # POCS reconstruction
...@@ -156,11 +169,11 @@ ...@@ -156,11 +169,11 @@
The POCS reconstruction is compared to a zero-filled reconstruction (i.e., where the missing data is zeroed prior to inverse Fourier Transform) The POCS reconstruction is compared to a zero-filled reconstruction (i.e., where the missing data is zeroed prior to inverse Fourier Transform)
In this section: In this section:
- print formatted strings to standard output - print formatted strings to standard output
- plotting, with min/max scales - 2D subplots with min/max scales, figure size
- np.sum sums over all elements by default - np.sum sums over all elements by default
%% Cell type:code id: tags: %% Cell type:code id: tags:
``` python ``` python
...@@ -174,15 +187,17 @@ ...@@ -174,15 +187,17 @@
# print errors # print errors
print(f'RMSE for zero-filled recon: {err_zf}') print(f'RMSE for zero-filled recon: {err_zf}')
print(f'RMSE for POCS recon: {err_pocs}') print(f'RMSE for POCS recon: {err_pocs}')
# plot both recons side-by-side # plot both recons side-by-side
_, ax = plt.subplots(1,2,figsize=(16,16)) _, ax = plt.subplots(2,2,figsize=(16,16))
# plot zero-filled # plot zero-filled
ax[0].imshow(np.abs(zf), vmin=0, vmax=1) ax[0,0].imshow(np.abs(zf), vmin=0, vmax=1)
ax[0].set_title('Zero-filled') ax[0,0].set_title('Zero-filled')
ax[1,0].plot(np.abs(zf[:,47]))
# plot POCS # plot POCS
ax[1].imshow(est, vmin=0, vmax=1) ax[0,1].imshow(est, vmin=0, vmax=1)
ax[1].set_title('POCS recon') ax[0,1].set_title('POCS recon')
ax[1,1].plot(np.abs(est[:,47]))
``` ```
......
...@@ -15,6 +15,10 @@ y = fftshift(fft2(img),1) + n; ...@@ -15,6 +15,10 @@ y = fftshift(fft2(img),1) + n;
% set bottom 24/96 lines to 0 % set bottom 24/96 lines to 0
y(73:end,:) = 0; y(73:end,:) = 0;
% show sampling
figure();
imshow(log(abs(fftshift(y,2))), [], 'colormap', jet)
%% Estimate phase %% Estimate phase
% create zero-padded hanning filter for ky-filtering % create zero-padded hanning filter for ky-filtering
filt = padarray(hann(48),24); filt = padarray(hann(48),24);
...@@ -25,6 +29,16 @@ low = ifft2(ifftshift(y.*filt,1)); ...@@ -25,6 +29,16 @@ low = ifft2(ifftshift(y.*filt,1));
% get phase image % get phase image
phs = exp(1j*angle(low)); phs = exp(1j*angle(low));
% show phase estimate alongside true phase
figure();
subplot(1,2,1);
imshow(angle(img), [-pi,pi], 'colormap', hsv);
title('True image phase');
subplot(1,2,2);
imshow(angle(phs), [-pi,pi], 'colormap', hsv)
title('Estimated phase');
%% POCS reconstruction %% POCS reconstruction
% initialise image estimate to be zeros % initialise image estimate to be zeros
est = zeros(96); est = zeros(96);
...@@ -74,11 +88,15 @@ fprintf(1, 'RMSE for POCS recon: %f\n', err_pocs); ...@@ -74,11 +88,15 @@ fprintf(1, 'RMSE for POCS recon: %f\n', err_pocs);
figure(); figure();
% plot zero-filled % plot zero-filled
subplot(1,2,1); subplot(2,2,1);
imshow(abs(zf), [0 1]); imshow(abs(zf), [0 1]);
title('Zero-Filled'); title('Zero-Filled');
subplot(2,2,3);
plot(abs(zf(:,48)), 'linewidth', 2);
% plot POCS % plot POCS
subplot(1,2,2); subplot(2,2,2);
imshow(est, [0 1]); imshow(est, [0 1]);
title('POCS recon'); title('POCS recon');
subplot(2,2,4);
plot(abs(est(:,48)), 'linewidth', 2);
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment