added codes
This commit is contained in:
3
matlab_code/eval_error.m
Normal file
3
matlab_code/eval_error.m
Normal file
@@ -0,0 +1,3 @@
|
||||
function err = eval_error(phi_w, ground)
|
||||
err = norm(phi_w(:) - ground(:), 2)/norm(ground(:), 2);
|
||||
end
|
||||
56
matlab_code/omme.m
Normal file
56
matlab_code/omme.m
Normal file
@@ -0,0 +1,56 @@
|
||||
function [motion_uw,dyn_range_uw,conf_uw,stdv]=omme(single_enc_motion,dyn_ranges)
|
||||
|
||||
%% Fast OPTIMAL MULTIPLE ENCODING RECONSTRUCTION (OMME-fast).
|
||||
% Also leads to best resuts when phase-contrast measurements are NOT
|
||||
% i.i.d., e.g. in case that reference phase measurement is measured only
|
||||
% once (as in 4 points 4D flow, for instance)
|
||||
%
|
||||
% Inputs:
|
||||
% single_enc_motion [Nvoxels,Ndynranges]: Example: vel in flow MRI. dphi*encEff/pi in MRE
|
||||
% dyn_ranges [1,Ndynranges]: relative dynamic ranges for each single_enc_motion data. Example: vencs in flow MRI, 1/encEff in MRE.
|
||||
%
|
||||
% Outputs:
|
||||
% motion_uw [Nvoxels,1]: unwrapped motion
|
||||
% dyn_range_uw [1,1]: new dynamic range after unwrapping
|
||||
% conf_uw [Nvoxels,1]: confidence image (should give 1 when measurements do
|
||||
% not have noise, and small when the noise is large)
|
||||
% stdv [1,1]: theoretical confidence in the estimated unwrapped motion
|
||||
|
||||
%% INIT
|
||||
|
||||
% Check correctness of input
|
||||
if length(dyn_ranges)~=size(single_enc_motion,2)
|
||||
error('Different number of dynamic ranges and encoded phases')
|
||||
end
|
||||
|
||||
if any(dyn_ranges<=0)
|
||||
error('Some dynamic ranges are smaller or equal to zero. Dynamic ranges need to be positive!')
|
||||
end
|
||||
|
||||
N=size(single_enc_motion,1); % number of voxels to be unwrapped
|
||||
motion_uw = zeros(N,1); % init unwrapped phases
|
||||
conf_uw = zeros(N,1); % init confidence
|
||||
|
||||
%% Optimal Multiple Encoding algorithm
|
||||
% New dynamic range (resulting from the combination)
|
||||
dyn_range_uw = double(lcm(sym(abs(dyn_ranges))));
|
||||
|
||||
% Sampling of u, according only to the smallest dyn_range
|
||||
[min_dynrange , ind] = min(abs(dyn_ranges)) ;
|
||||
nb_of_samples = ceil(dyn_range_uw/min_dynrange)+2 ; % This is for covering the whole range [-dyn_range_uw,dyn_range_uw]
|
||||
% Phase-contrast motion for smallest dyn_range +- min_dyn_range*k candidates
|
||||
range_u = (-nb_of_samples:nb_of_samples)*min_dynrange;
|
||||
u = single_enc_motion(:,ind)*ones(1,length(range_u)) + ones(N,1)*range_u ;
|
||||
|
||||
for k=1:N % loop over all voxels
|
||||
Jmulti = 0 ;
|
||||
u_k = u(k,abs(u(k,:))<=dyn_range_uw); % Candidates only in the effective dynamic range
|
||||
for i=1:length(dyn_ranges)
|
||||
Jmulti = Jmulti - cos( pi*( single_enc_motion(k,i) - u_k )/dyn_ranges(i) );
|
||||
end
|
||||
[~,ind_k] = min(Jmulti);
|
||||
motion_uw(k) = u_k(ind_k);
|
||||
% Evaluate confidence of the estimation by computing second derivative of the cost function
|
||||
conf_uw(k) = sum( cos( pi*( single_enc_motion(k,:) - motion_uw(k) )./dyn_ranges )./(dyn_ranges.^2) )/sum( 1./(dyn_ranges.^2) ) ;
|
||||
end
|
||||
stdv = min_dynrange; % Theoretical standard deviation of the unwrapped estimator (= to empirical for inf realizations)
|
||||
67
matlab_code/probability.m
Normal file
67
matlab_code/probability.m
Normal file
@@ -0,0 +1,67 @@
|
||||
function phi = probability(phi_w, t_low, t_high, w_s, w_t)
|
||||
si = size(phi_w);
|
||||
function p = prob_pass(phi_w, threshold)
|
||||
p = phi_w;
|
||||
pw = 0;
|
||||
for x=1:si(1)
|
||||
for y=1:si(2)
|
||||
for z=1:si(3)
|
||||
for t=1:si(4)
|
||||
grad_sum = 0;
|
||||
val = phi_w(x, y, z, t);
|
||||
tot = 0;
|
||||
if 1<x
|
||||
grad_sum = grad_sum + w_s*(phi_w(x-1, y, z, t) - val);
|
||||
tot = tot + w_s;
|
||||
end
|
||||
if x<si(1)-1
|
||||
grad_sum = grad_sum + w_s*(phi_w(x+1, y, z, t) - val);
|
||||
tot = tot + w_s;
|
||||
end
|
||||
if 1<y
|
||||
grad_sum = grad_sum + w_s*(phi_w(x, y-1, z, t) - val);
|
||||
tot = tot + w_s;
|
||||
end
|
||||
if y<si(2)-1
|
||||
grad_sum = grad_sum + w_s*(phi_w(x, y+1, z, t) - val);
|
||||
tot = tot + w_s;
|
||||
end
|
||||
if 1<z
|
||||
grad_sum = grad_sum + w_s*(phi_w(x, y, z-1, t) - val);
|
||||
tot = tot +w_s;
|
||||
end
|
||||
if z<si(3)-1
|
||||
grad_sum = grad_sum + w_s*(phi_w(x, y, z+1, t) - val);
|
||||
tot =tot +w_s;
|
||||
end
|
||||
if 1<t
|
||||
grad_sum = grad_sum + w_t*(phi_w(x, y, z, t-1) - val);
|
||||
tot = tot +w_t;
|
||||
end
|
||||
if t<si(4)-1
|
||||
grad_sum = grad_sum + w_t*(phi_w(x, y, z, t+1) - val);
|
||||
tot = tot +w_t;
|
||||
end
|
||||
prob = grad_sum /(2*pi*tot);
|
||||
if prob > threshold
|
||||
p(x, y, z, t) = val + 2*pi;
|
||||
pw = pw +1;
|
||||
end
|
||||
if prob < -threshold
|
||||
p(x, y, z, t) = val - 2*pi;
|
||||
pw = pw +1;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
pw;
|
||||
end
|
||||
phi = prob_pass(phi_w, t_low);
|
||||
for i =1:9
|
||||
phi = prob_pass(phi, t_low);
|
||||
end
|
||||
for i=1:10
|
||||
phi = prob_pass(phi, t_high);
|
||||
end
|
||||
end
|
||||
17
matlab_code/temporal.m
Normal file
17
matlab_code/temporal.m
Normal file
@@ -0,0 +1,17 @@
|
||||
function phi = temporal(phi_w, t_ref)
|
||||
%si = size(phi_w);
|
||||
phi = zeros(size(phi_w));
|
||||
phi(:, :, :, t_ref) = phi_w(:, :, :, t_ref);
|
||||
phi_diff = zeros(size(phi_w));
|
||||
for i = t_ref:size(phi_w, 4)-1
|
||||
phi_diff(:, :, :, i) = phi_w(:, :, :, i+1) - phi_w(:, :, :, i);
|
||||
phi_diff(:, :, :, i) = phi_diff(:, :, :, i) + 2*pi*(phi_diff(:, :, :, i)<-pi);
|
||||
phi_diff(:, :, :, i) = phi_diff(:, :, :, i) - 2*pi*(phi_diff(:, :, :, i)>pi);
|
||||
phi(:, :, :, i+1) = phi(:, :, :, i) + phi_diff(:, :, :, i);
|
||||
end
|
||||
for i = t_ref-1:-1:1
|
||||
phi_diff(:, :, :, i) = phi_w(:, :, :, i+1) - phi_w(:, :, :, i);
|
||||
phi_diff(:, :, :, i) = phi_diff(:, :, :, i) + 2*pi*(phi_diff(:, :, :, i)<-pi);
|
||||
phi_diff(:, :, :, i) = phi_diff(:, :, :, i) - 2*pi*(phi_diff(:, :, :, i)>pi);
|
||||
phi(:, :, :, i) = phi(:, :, :, i+1) - phi_diff(:, :, :, i);
|
||||
end
|
||||
114
matlab_code/unwrap.m
Normal file
114
matlab_code/unwrap.m
Normal file
@@ -0,0 +1,114 @@
|
||||
%%PHASE UNWRAP
|
||||
%unwraps given data with three different unwrapping methods
|
||||
%compares quantitatively to OMME results
|
||||
%%
|
||||
clear
|
||||
clc
|
||||
|
||||
%these are from the repository for the Loecher 2014 paper
|
||||
addpath('4dflow-lapunwrap/utils');
|
||||
addpath('4dflow-lapunwrap/unwrap');
|
||||
%%
|
||||
struct = load('path_to_data_file');
|
||||
wrapped = struct.pca_p;
|
||||
mask_struct = load('path_to_mask_file');
|
||||
mask = mask_struct.labels;
|
||||
si = size(wrapped);
|
||||
si(3) = 15;
|
||||
phi = zeros(si(1), si(2), 1, si(3));
|
||||
noise_std_percent = 0.15;
|
||||
noise_std = noise_std_percent *pi;
|
||||
rng('default')
|
||||
rng(100 + file{1}(2))
|
||||
noise = noise_std.*randn(si);
|
||||
phi(:, :, 1, 1:si(3)) = (wrapped(:, :, 1:si(3)) + noise).*mask(:, :, 1:si(3));
|
||||
phi_wn = zeros(si(1), si(2), 1, si(3));
|
||||
phi_wn(:, :, 1, 1:si(3)) = (wrapped(:, :, 1:si(3))).*mask(:, :, 1:si(3));
|
||||
phi = phi - 2*pi*(phi > pi);
|
||||
phi = phi + 2*pi*(phi < -pi);
|
||||
masked = zeros(si(1), si(2), si(3));
|
||||
masked(:, :, :) = phi(:, :, 1, :);
|
||||
|
||||
%%
|
||||
%laplacian unwrap
|
||||
tic
|
||||
n_u4 = unwrap_4D(phi);
|
||||
toc
|
||||
lap4d_phi = phi + double(n_u4).*2*pi;
|
||||
n_u3 = zeros(size(n_u4), 'int8');
|
||||
tic
|
||||
for i=1:si(3)
|
||||
n_u3(:, :, :, i) = unwrap_3D(phi(:, :, :, i));
|
||||
end
|
||||
lap3d_phi = phi + double(n_u3).*2*pi;
|
||||
toc
|
||||
|
||||
%%
|
||||
%temporal unwrap
|
||||
t_ref = 15;
|
||||
tic
|
||||
temp_phi = temporal(phi, t_ref);
|
||||
toc
|
||||
|
||||
%%
|
||||
%probability unwrap
|
||||
w_s = 1.0;
|
||||
w_t = 2.5;
|
||||
t_low = 0.32;
|
||||
t_high = 0.75;
|
||||
tic
|
||||
prob_phi = probability(phi, t_low, t_high, w_s, w_t);
|
||||
toc
|
||||
|
||||
%%
|
||||
%omme
|
||||
struct = load('path_to_higher_venc_file');
|
||||
high_data = struct.pca_p;
|
||||
high_venc = zeros(size(phi));
|
||||
high_venc(:, :, 1, :) = (high_data(:, :, 1:si(3))).*mask(:, :, 1:si(3));
|
||||
highv = 150;
|
||||
lowv = 75;
|
||||
high_venc = high_venc.*(highv/pi);
|
||||
low_venc = phi.*(lowv/pi);
|
||||
tic
|
||||
[omme_v, dyn, conf, std] = omme([high_venc(:), low_venc(:)], [highv, lowv]);
|
||||
omme_v = reshape(omme_v, [si(1), si(2), 1, si(3)]);
|
||||
toc
|
||||
|
||||
%%
|
||||
%evaluate!
|
||||
temp_v = temp_phi.*lowv/pi;
|
||||
lap3d_v = lap3d_phi.*lowv/pi;
|
||||
lap4d_v = lap4d_phi.*lowv/pi;
|
||||
prob_v = prob_phi.*lowv/pi;
|
||||
v = phi.*lowv/pi;
|
||||
|
||||
t = 1:si(3);
|
||||
base_error = eval_error(v(:, :, 1, t), omme_v(:, :, 1, t))
|
||||
t_error = eval_error(temp_v(:, :, 1, t), omme_v(:, :, 1, t))
|
||||
l4_error = eval_error(lap4d_v(:, :, 1, t), omme_v(:, :, 1, t))
|
||||
l3_error = eval_error(lap3d_v(:, :, 1, t), omme_v(:, :, 1, t))
|
||||
prob_error = eval_error(prob_v(:, :, 1, t), omme_v(:, :, 1, t))
|
||||
|
||||
%%
|
||||
%display!
|
||||
t = 4;
|
||||
slice = 1;
|
||||
h = 145:180;
|
||||
w = 35:80;
|
||||
im0 = v(h, w, slice, t);
|
||||
im1 = temp_v(h, w, slice, t);
|
||||
im2 = lap4d_v(h, w, slice, t);
|
||||
im4 = prob_v(h, w, slice, t);
|
||||
im3 = omme_v(h, w, slice, t);
|
||||
im5 = lap3d_v(h, w, slice, t);
|
||||
figure();
|
||||
|
||||
imshow([[im0 im3 im1], [im5, im2 im4]], [], 'border', 'tight', 'InitialMagnification', 300)
|
||||
axis off
|
||||
colormap("jet")
|
||||
a = colorbar
|
||||
ylabel(a,'velocity (cm/s)')
|
||||
caxis([-160, 220])
|
||||
axis off
|
||||
|
||||
75
matlab_code/unwrap_comparison.m
Normal file
75
matlab_code/unwrap_comparison.m
Normal file
@@ -0,0 +1,75 @@
|
||||
function [errors] = unwrap_comparison(file,t_end, noise_std_percent)
|
||||
%unwraps a given file with all five methods (Temporal, 3D Laplacian, 4D
|
||||
%Laplacian, Probability, OMME)
|
||||
%always uses file with Venc 75 and Venc 150
|
||||
%returns arrays of errors (as compared to OMME)
|
||||
struct = load('path_to_data_file');
|
||||
wrapped = struct.pca_p;
|
||||
mask_struct = load('path_to_mask_file');
|
||||
mask = mask_struct.labels;
|
||||
si = size(wrapped);
|
||||
si(3) = t_end;
|
||||
phi = zeros(si(1), si(2), 1, si(3));
|
||||
rng('default')
|
||||
rng(100 + str2double(file{1}(2)))
|
||||
noise_std = noise_std_percent * pi
|
||||
noise = noise_std.*randn(si);
|
||||
phi(:, :, 1, 1:si(3)) = (wrapped(:, :, 1:si(3)) + noise).*mask(1:si(1), 1:si(2), 1:si(3));
|
||||
phi_wn = zeros(si(1), si(2), 1, si(3));
|
||||
phi_wn(:, :, 1, 1:si(3)) = (wrapped(:, :, 1:si(3))).*mask(1:si(1), 1:si(2), 1:si(3));
|
||||
phi = phi - 2*pi*(phi > pi);
|
||||
phi = phi + 2*pi*(phi < -pi);
|
||||
|
||||
%%
|
||||
%laplacian unwrap
|
||||
n_u4 = unwrap_4D(phi);
|
||||
lap4d_phi = phi + double(n_u4).*2*pi;
|
||||
n_u3 = zeros(size(n_u4), 'int8');
|
||||
for i=1:si(3)
|
||||
n_u3(:, :, :, i) = unwrap_3D(phi(:, :, :, i));
|
||||
end
|
||||
lap3d_phi = phi + double(n_u3).*2*pi;
|
||||
|
||||
%%
|
||||
%temporal unwrap
|
||||
t_ref = t_end;
|
||||
temp_phi = temporal(phi, t_ref);
|
||||
|
||||
%%
|
||||
%probability unwrap
|
||||
w_s = 1.0;
|
||||
w_t = 2.5;
|
||||
t_low = 0.32;
|
||||
t_high = 0.75;
|
||||
prob_phi = probability(phi, t_low, t_high, w_s, w_t);
|
||||
|
||||
%%
|
||||
%omme
|
||||
struct = load('path_to_higher_venc_data_file');
|
||||
high_data = struct.pca_p;
|
||||
high_venc = zeros(size(phi));
|
||||
high_venc(:, :, 1, :) = (high_data(:, :, 1:si(3))).*mask(:, :, 1:si(3));
|
||||
highv = 150;
|
||||
lowv = 50;
|
||||
high_venc = high_venc.*(highv/pi);
|
||||
low_venc = phi_wn.*(lowv/pi);
|
||||
[omme_v, dyn, conf, std] = omme([high_venc(:), low_venc(:)], [highv, lowv]);
|
||||
omme_v = reshape(omme_v, [si(1), si(2), 1, si(3)]);
|
||||
|
||||
%%
|
||||
%evaluate!
|
||||
temp_v = temp_phi.*lowv/pi;
|
||||
lap3d_v = lap3d_phi.*lowv/pi;
|
||||
lap4d_v = lap4d_phi.*lowv/pi;
|
||||
prob_v = prob_phi.*lowv/pi;
|
||||
v = phi.*lowv/pi;
|
||||
|
||||
t = 1:si(3);
|
||||
base_error = eval_error(v(:, :, 1, t), high_venc(:, :, 1, t));
|
||||
t_error = eval_error(temp_v(:, :, 1, t), high_venc(:, :, 1, t));
|
||||
l4_error = eval_error(lap4d_v(:, :, 1, t), high_venc(:, :, 1, t));
|
||||
l3_error = eval_error(lap3d_v(:, :, 1, t), high_venc(:, :, 1, t));
|
||||
prob_error = eval_error(prob_v(:, :, 1, t), high_venc(:, :, 1, t));
|
||||
omme_error = eval_error(omme_v(:, :, 1, t), high_venc(:, :, 1, t));
|
||||
errors = [base_error, t_error, l3_error, l4_error, prob_error, omme_error]
|
||||
end
|
||||
Reference in New Issue
Block a user