NuMRI/codes/SENSE.py

116 lines
4.0 KiB
Python

import numpy as np
from numpy import linalg as LA
import sys
from mpi4py import MPI
comm = MPI.COMM_WORLD
size = comm.Get_size()
rank = comm.Get_rank()
# SENSE: Simulation of SENSitive Encoding algorithm proposed by K. Pruessmann, et. al. in:
# "SENSE: Sensitivity Enconding for Fast MRI" Mag. Res. in Medicine 42. (1999)
# written by Jeremias Garay (j.e.garay.labra@rug.nl)
def Sensitivity_Map(shape):
[Nx,Ny,Nz] = shape
[X,Y,Z] = np.meshgrid(np.linspace(0,Ny,Ny),np.linspace(0,Nx,Nx),np.linspace(0,Nz,Nz))
Xsense1 = (X/(Nx*2)-1)**2
Xsense2 = ((Nx-X)/(Nx*2)-1)**2
S_MAPS = [np.fft.fftshift(Xsense1),np.fft.fftshift(Xsense2)]
return S_MAPS
def SENSE_recon(S1,M1,S2,M2):
[Nx,Ny,Nz,Nt] = M1.shape
M = np.zeros([Nx,int(2*Ny),Nz,Nt],dtype=complex)
sm1 = np.fft.fftshift(S1)[:,:,0]
sm2 = np.fft.fftshift(S2)[:,:,0]
for j in range(Ny):
for k in range(Nx):
l1 = M1[k,j,:,:]; a1 = sm1[k,j]; a2 = sm1[k,j+Ny]
l2 = M2[k,j,:,:]; b1 = sm2[k,j]; b2 = sm2[k,j+Ny]
B = (l1*b1 - l2*a1)/(a2*b1 - b2*a1)
A = (l1*b2 - l2*a2)/(a1*b2 - a2*b1)
M[k,j,:,:] = A
M[k,j+Ny,:,:] = B
return M
def SENSE_recon2(S1,M1,S2,M2):
# With matrices as in the original paper!
[Nx,Ny,Nz,Nt] = M1.shape
M = np.zeros([Nx,int(2*Ny),Nz,Nt],dtype=complex)
sm1 = np.fft.fftshift(S1)[:,:,0]
sm2 = np.fft.fftshift(S2)[:,:,0]
sigma2 = 0.049**2
sigma2 = 1
Psi = np.diagflat(np.array([sigma2,sigma2])) # Error matrix Psi
Psi_inv = np.linalg.inv(Psi)
for j in range(Ny):
for k in range(Nx):
l1 = M1[k,j,:,:]; a1 = sm1[k,j]; a2 = sm1[k,j+Ny]
l2 = M2[k,j,:,:]; b1 = sm2[k,j]; b2 = sm2[k,j+Ny]
S = np.array([[a1,a2],[b1,b2]])
U = np.linalg.inv((np.transpose(S)*Psi_inv*S))*np.transpose(S)*Psi_inv
a = np.array([l1,l2])
a_resized = np.resize(a,(2,Nz*Nt))
v_resized = np.dot(U,a_resized)
v = np.resize(v_resized,(2,Nz,Nt))
M[k,j,:,:] = v[0,:,:]
M[k,j+Ny,:,:] = v[1,:,:]
return M
def SENSE_METHOD(Seq,R):
'''
Args:
ITOT: a numpy matrix with the full sampled (3D or 4D) dynamical data
R: the acceleration factor
'''
[row,col,dep,numt2] = Seq.shape
Seq_red = {}
SenseMAP = {}
[SenseMAP[0],SenseMAP[1]] = Sensitivity_Map([row,col,dep])
col2 = int(np.ceil(col/2))
for rs in range(R):
Seq_red[rs] = np.zeros([row,col2,dep,numt2],dtype=complex)
for t in range(numt2):
Kdata_0 = np.fft.fftn(Seq[:,:,:,t])
Kdata_0 = Kdata_0*SenseMAP[rs]
Kdata_0 = Kdata_0[:,0::R,:]
Seq_red[rs][:,:,:,t] = np.fft.ifftn(Kdata_0)
Seq_recon = SENSE_recon2(SenseMAP[0],Seq_red[0],SenseMAP[1],Seq_red[1])
return Seq_recon
def undersampling(Mx,My,Mz,options):
R = options['SENSE']['R']
for r in R:
if rank==0:
print('Using Acceleration Factor R = ' + str(r))
print('applying into x component')
Mx_s = SENSE_METHOD(Mx,r)
if rank==0:
print('applying into y component')
My_s = SENSE_METHOD(My,r)
if rank==0:
print('applying into z component')
Mz_s = SENSE_METHOD(Mz,r)
return [Mx_s,My_s,Mz_s]