871 lines
32 KiB
Python
871 lines
32 KiB
Python
import numpy as np
|
|
import scipy as sc
|
|
from scipy import signal
|
|
from mpi4py import MPI
|
|
comm = MPI.COMM_WORLD
|
|
size = comm.Get_size()
|
|
rank = comm.Get_rank()
|
|
|
|
|
|
|
|
# kt-BLAST (NO DC TERM) method for reconstruction of undersampled MRI image based on
|
|
# l2 minimization.
|
|
|
|
def EveryAliased3D2(i,j,k,PP,Nx,Ny,Nz,BB,R):
|
|
|
|
ivec = [i,j,k]
|
|
Nvec = [Nx,Ny,Nz]
|
|
[ktot,ltot] = PP.shape
|
|
Ptot = np.zeros([ktot**ltot,ltot])
|
|
PP2 = np.zeros([ktot**ltot,ltot])
|
|
tt = -1
|
|
|
|
for kk in range(Ptot.shape[0]):
|
|
nn = int(np.mod(kk,3))
|
|
mm = int(np.mod(np.floor(kk/3),3))
|
|
if np.mod(kk,9)==0:
|
|
tt+=1
|
|
|
|
Ptot[kk,0] = PP[tt,0] + ivec[0]
|
|
Ptot[kk,1] = PP[mm,1] + ivec[1]
|
|
Ptot[kk,2] = PP[nn,2] + ivec[2]
|
|
|
|
for kk in range(Ptot.shape[0]):
|
|
for ll in range(Ptot.shape[1]):
|
|
if Ptot[kk,ll]<0:
|
|
Ptot[kk,ll] = Ptot[kk,ll] + Nvec[ll]
|
|
if Ptot[kk,ll]>=Nvec[ll]:
|
|
Ptot[kk,ll] = Ptot[kk,ll] - Nvec[ll]
|
|
|
|
|
|
CC = np.zeros([3,Ptot.shape[0]+1])
|
|
YY = np.array([ [i] , [j], [k] ])
|
|
CC[0,0] = i
|
|
CC[1,0] = j
|
|
CC[2,0] = k
|
|
psel = 0
|
|
|
|
|
|
for l in range(1,Ptot.shape[0]+1):
|
|
CC[0,l] = int(Ptot[l-1,0])
|
|
CC[1,l] = int(Ptot[l-1,1])
|
|
CC[2,l] = int(Ptot[l-1,2])
|
|
|
|
|
|
|
|
if CC[0,l]==YY[0,psel] and CC[1,l]==YY[1,psel] and CC[2,l]==YY[2,psel] and BB[int(CC[1,l]),int(CC[2,l]),int(CC[0,l])]!=0:
|
|
pass
|
|
else:
|
|
War = False
|
|
for ww in range(psel):
|
|
if CC[0,l]==YY[0,ww] and CC[1,l]==YY[1,ww] and CC[2,l]==YY[2,ww] and BB[int(CC[1,l]),int(CC[2,l]),int(CC[0,l])]!=0:
|
|
War = True
|
|
|
|
if not War:
|
|
psel += 1
|
|
CCC = np.array([ [CC[0,l] ] , [CC[1,l]] , [CC[2,l]]])
|
|
YY = np.concatenate( ( YY, CCC ) ,axis=1 )
|
|
|
|
return YY.astype(int)
|
|
|
|
def EveryAliased3D(i,j,k,DP,Nx,Ny,Nz,BB,R,SPREAD=None):
|
|
|
|
ivec = [i,j,k]
|
|
Nvec = [Nx,Ny,Nz]
|
|
[ktot,ltot] = DP.shape
|
|
DPN = np.zeros([ktot,ltot])
|
|
|
|
if SPREAD is not None: # WITH SPREAD FUNCTIONS FORMALISM
|
|
Maux = np.zeros([Ny,Nz,Nx])
|
|
Maux[j,k,i] = 1
|
|
SP2 = SPREAD[::-1,::-1,::-1]
|
|
MS = R*sc.signal.convolve(Maux,SP2, mode='same')
|
|
ms = np.abs(MS)
|
|
Ims = 1*(ms>np.max(ms)*0.405)
|
|
Pas = np.where(Ims==1)
|
|
PP = np.array(Pas[:])
|
|
PEA = PP[::-1,:]
|
|
|
|
for ll in range(PEA.shape[1]):
|
|
if PEA[0,ll]>=Nx:
|
|
PEA[0,ll] = PEA[0,ll] - Nx
|
|
if PEA[1,ll]>=Ny:
|
|
PEA[1,ll] = PEA[1,ll] - Ny
|
|
if PEA[2,ll]>=Nz:
|
|
PEA[2,ll] = PEA[2,ll] - Nz
|
|
|
|
|
|
Ntot = PEA.shape[1]
|
|
ind = 0
|
|
PEAnew = PEA
|
|
|
|
|
|
for ll in range(Ntot):
|
|
if BB[PEA[1,ll],PEA[2,ll],PEA[0,ll]]!=0:
|
|
PEAnew = np.delete(PEAnew,(ll-ind),axis=1)
|
|
ind +=1
|
|
|
|
|
|
return PEA
|
|
else:
|
|
|
|
for kk in range(DPN.shape[0]):
|
|
for l in range(DPN.shape[1]):
|
|
DPN[kk,l] = DP[kk,l] + ivec[l]
|
|
if DPN[kk,l]<0:
|
|
DPN[kk,l] = DPN[kk,l] + Nvec[l]
|
|
if DPN[kk,l]>=Nvec[l]:
|
|
DPN[kk,l] = DPN[kk,l] - Nvec[l]
|
|
|
|
|
|
|
|
CC = np.zeros([3,ktot+1])
|
|
YY = np.array([ [i] , [j], [k] ])
|
|
CC[0,0] = i
|
|
CC[1,0] = j
|
|
CC[2,0] = k
|
|
|
|
|
|
for l in range(1,ktot+1):
|
|
CC[0,l] = DPN[l-1,0]
|
|
CC[1,l] = DPN[l-1,1]
|
|
CC[2,l] = DPN[l-1,2]
|
|
|
|
if CC[0,l]!=CC[0,l-1] and CC[1,l]!=CC[1,l-1] and CC[2,l]!=CC[2,l-1] and BB[int(CC[1,l]),int(CC[2,l]),int(CC[0,l])]==0:
|
|
CCC = np.array([ [CC[0,l] ] , [CC[1,l]] , [CC[2,l]]])
|
|
YY = np.concatenate( ( YY, CCC ) ,axis=1 )
|
|
|
|
return YY.astype(int)
|
|
|
|
def EveryAliased(i,j,DP,Nx,Ny,BB,R,mode):
|
|
|
|
if mode==1: # USING GEOMETRICAL ASSUMPTIONS
|
|
ivec = [i,j]
|
|
Nvec = [Nx,Ny]
|
|
DPN = 0*DP
|
|
[ktot,ltot] = DP.shape
|
|
|
|
for k in range(ktot):
|
|
for l in range(ltot):
|
|
|
|
DPN[k,l] = DP[k,l] + ivec[l]
|
|
|
|
if DPN[k,l]<0:
|
|
#DPN[k,l] = ivec[l]
|
|
DPN[k,l] = DPN[k,l] + Nvec[l]
|
|
|
|
if DPN[k,l]>=Nvec[l]:
|
|
#DPN[k,l] = ivec[l]
|
|
DPN[k,l] = DPN[k,l] - Nvec[l]
|
|
|
|
CC = np.zeros([2,ktot+1])
|
|
YY = np.array([ [i] , [j] ])
|
|
CC[0,0] = i
|
|
CC[1,0] = j
|
|
|
|
for l in range(1,ktot+1):
|
|
CC[0,l] = DPN[l-1,0]
|
|
CC[1,l] = DPN[l-1,1]
|
|
if CC[0,l]!=CC[0,l-1] and CC[1,l]!=CC[1,l-1] and BB[int(CC[1,l]),int(CC[0,l])]==0:
|
|
CCC = np.array([ [CC[0,l] ] , [CC[1,l]] ])
|
|
YY = np.concatenate( ( YY, CCC ) ,axis=1 )
|
|
|
|
return YY.astype(int)
|
|
|
|
|
|
|
|
if mode=='spread': # WITH SPREAD FUNCTIONS FORMALISM
|
|
Maux = np.zeros([row,numt2])
|
|
Maux[l,k] = 1
|
|
MS = R*ConvolSP(Maux,SPREAD)
|
|
ms = np.abs(MS)
|
|
Ims = 1*(ms>np.max(ms)*0.405)
|
|
Pas = np.where(Ims==1)
|
|
PP = np.array(Pas[:])
|
|
return PP[::-1,:]
|
|
|
|
def GetSymmetric(M):
|
|
[row,numt2] = M.shape
|
|
S = np.zeros(M.shape,dtype=complex)
|
|
aux = np.zeros([1,row])
|
|
nmid = 0.5*(numt2+1)
|
|
for k in range(int(nmid)):
|
|
aux = 0.5*( M[:,k] + M[:,numt2-k-1] )
|
|
S[:,k] = aux
|
|
S[:,numt2-k-1] = aux
|
|
|
|
return S
|
|
|
|
def UNDER(A,mode,R,k):
|
|
|
|
start = np.mod(k,R)
|
|
I1B = np.zeros(A.shape,dtype=complex)
|
|
|
|
# Not quite efficient ! better to work with vectors
|
|
|
|
if mode=='ky':
|
|
for k in range(start,A.shape[0],R):
|
|
I1B[k,:,:] = A[k,:,:]
|
|
|
|
if mode=='kxky':
|
|
for k in range(start,A.shape[0],R):
|
|
for l in range(start,A.shape[1],R):
|
|
I1B[k,l,:] = A[k,l,:]
|
|
|
|
if mode=='kxkykz':
|
|
for k in range(start,A.shape[0],R):
|
|
for l in range(start,A.shape[2],R):
|
|
for r in range(start,A.shape[1],R):
|
|
I1B[k,r,l] = A[k,r,l]
|
|
|
|
|
|
return I1B
|
|
|
|
def FilteringHigh(M,fac):
|
|
|
|
if M.ndim==2:
|
|
|
|
[row,col] = M.shape
|
|
inx = np.linspace(0,col-1,col)
|
|
MF = np.zeros(M.shape,dtype=complex)
|
|
|
|
for k in range(row):
|
|
vecfou = np.fft.fft(M[k,:])
|
|
window = signal.tukey(2*col,fac)
|
|
vecfou2 = vecfou*window[col:2*col]
|
|
MF[k,:] = np.fft.ifft(vecfou2)
|
|
|
|
return MF
|
|
|
|
|
|
if M.ndim==3:
|
|
[row,col,dep] = M.shape
|
|
MF = np.zeros(M.shape,dtype=complex)
|
|
inx = np.linspace(0,col-1,col)
|
|
for l in range(dep):
|
|
for k in range(row):
|
|
vecfou = np.fft.fft(M[k,:,l])
|
|
window = signal.tukey(2*col,fac)
|
|
vecfou2 = vecfou*window[col:2*col]
|
|
MF[k,:,l] = np.fft.ifft(vecfou2)
|
|
|
|
|
|
return MF
|
|
|
|
def InterpolateM(M,numt2):
|
|
|
|
if M.ndim==2:
|
|
|
|
[row,numt] = M.shape
|
|
MNew = np.zeros([row,numt2],dtype=complex)
|
|
xdat = np.linspace(0,numt,numt)
|
|
xdat2 = np.linspace(0,numt,numt2)
|
|
nstar = int(0.5*(numt2-numt))
|
|
|
|
for t in range(nstar,nstar+numt):
|
|
MNew[:,t] = M[:,t-nstar]
|
|
|
|
for l in range(row):
|
|
ydat = M[l,:]
|
|
fdat = sc.interpolate.interp1d(xdat,ydat,kind='cubic')
|
|
MNew[l,1:nstar] = fdat(xdat2)[1:nstar]
|
|
MNew[l,nstar+numt:numt2] = fdat(xdat2)[nstar+numt:numt2]
|
|
|
|
|
|
if M.ndim==3:
|
|
[row,col,numt] = M.shape
|
|
MNew = np.zeros([row,col,numt2],dtype=complex)
|
|
xdat = np.linspace(0,numt,numt)
|
|
xdat2 = np.linspace(0,numt,numt2)
|
|
nstar = int(0.5*(numt2-numt))
|
|
for t in range(nstar,nstar+numt):
|
|
MNew[:,:,t] = M[:,:,t-nstar]
|
|
|
|
for c in range(col):
|
|
for l in range(row):
|
|
ydat = M[l,c,:]
|
|
fdat = sc.interpolate.interp1d(xdat,ydat,kind='cubic')
|
|
MNew[l,c,1:nstar] = fdat(xdat2)[1:nstar]
|
|
MNew[l,c,nstar+numt:numt2] = fdat(xdat2)[nstar+numt:numt2]
|
|
|
|
|
|
return MNew
|
|
|
|
def KTT(M,scol):
|
|
|
|
#Maux = M[:,scol,:]
|
|
#Maux = np.fft.ifftshift(Maux,axes=0)
|
|
#Maux = np.fft.ifft(Maux,axis=0)
|
|
#Maux = np.fft.ifft(Maux,axis=1)
|
|
#Maux = np.fft.fftshift(Maux,axes=1)
|
|
|
|
# TAO STYLE
|
|
Maux = np.zeros(M.shape,dtype=complex)
|
|
|
|
for k in range(M.shape[2]):
|
|
Maux[:,:,k] = np.fft.ifftshift(M[:,:,k])
|
|
Maux[:,:,k] = np.fft.ifft2(Maux[:,:,k])
|
|
Maux = Maux[:,scol,:]
|
|
Maux = np.fft.ifft(Maux,axis=1)
|
|
Maux = np.fft.fftshift(Maux,axes=1)
|
|
return Maux
|
|
|
|
def IKTT(M):
|
|
|
|
#Maux = np.fft.ifftshift(M,axes=1)
|
|
#Maux = np.fft.ifft(Maux,axis=1)
|
|
#Maux = np.fft.fft(Maux,axis=0)
|
|
#Maux = np.fft.fftshift(Maux,axes=0)
|
|
|
|
# TAO STYLE
|
|
Maux = np.fft.ifftshift(M,axes=1)
|
|
Maux = np.fft.fft(Maux,axis=1)
|
|
|
|
return Maux
|
|
|
|
def KTT3D(M,sdep):
|
|
|
|
Maux = np.zeros(M.shape,dtype=complex)
|
|
for k in range(M.shape[3]):
|
|
Maux[:,:,:,k] = np.fft.ifftshift(M[:,:,:,k])
|
|
Maux[:,:,:,k] = np.fft.ifftn(Maux[:,:,:,k])
|
|
Maux = Maux[:,:,sdep,:]
|
|
Maux = np.fft.ifft(Maux,axis=2)
|
|
Maux = np.fft.fftshift(Maux,axes=2)
|
|
return Maux
|
|
|
|
def IKTT3D(M):
|
|
|
|
Maux = np.fft.ifftshift(M,axes=2)
|
|
Maux = np.fft.fft(Maux,axis=2)
|
|
|
|
return Maux
|
|
|
|
def get_points4D(row,col,dep,numt2,R,mode):
|
|
|
|
bb = np.ceil(row/R)
|
|
cc = np.ceil(col/R)
|
|
aa = np.ceil(numt2/R)
|
|
points = R+1
|
|
kmid = int(R/2)
|
|
|
|
if mode=='kxky':
|
|
PC = [np.ceil(numt2/2),np.ceil(row/2),np.ceil(col/2)]
|
|
PP = np.zeros([points,3])
|
|
DP = np.zeros([points-1,3])
|
|
for k in range(points):
|
|
|
|
PP[k,0] = numt2-aa*(k) + 1
|
|
PP[k,1] = bb*(k)
|
|
PP[k,2] = cc*(k)
|
|
|
|
if PP[k,0]>=numt2:
|
|
PP[k,0] -= 1
|
|
if PP[k,0]<0:
|
|
PP[k,0] += 1
|
|
|
|
if PP[k,1]>=row:
|
|
PP[k,1] -= 1
|
|
if PP[k,1]<0:
|
|
PP[k,1] += 1
|
|
|
|
if PP[k,2]>=col:
|
|
PP[k,2] -= 1
|
|
if PP[k,2]<0:
|
|
PP[k,2] += 1
|
|
|
|
if k<kmid:
|
|
DP[k,0] = PP[k,0] - PC[0]
|
|
DP[k,1] = PP[k,1] - PC[1]
|
|
DP[k,2] = PP[k,2] - PC[2]
|
|
if k>kmid:
|
|
DP[k-1,0] = PP[k,0] - PC[0]
|
|
DP[k-1,1] = PP[k,1] - PC[1]
|
|
DP[k-1,2] = PP[k,2] - PC[2]
|
|
|
|
kmax = int((PP[kmid,0] + PP[kmid-1,0])/2 )
|
|
kmin = int((PP[kmid,0] + PP[kmid+1,0])/2 )
|
|
cmax = int((PP[kmid,1] + PP[kmid-1,1])/2 )
|
|
cmin = int((PP[kmid,1] + PP[kmid+1,1])/2 )
|
|
|
|
|
|
#DP2 = np.zeros([DP.shape[0]**DP.shape[1],DP.shape[1]])
|
|
#DP2[0,0] = DP[0,0]; DP2[0,1] = DP[0,1] ; DP2[0,2] = DP[0,2]
|
|
#DP2[1,0] = DP[0,0]; DP2[1,1] = DP[0,1] ; DP2[1,2] = DP[1,2]
|
|
#DP2[2,0] = DP[0,0]; DP2[2,1] = DP[1,1] ; DP2[2,2] = DP[0,2]
|
|
#DP2[3,0] = DP[0,0]; DP2[3,1] = DP[1,1] ; DP2[3,2] = DP[1,2]
|
|
#DP2[4,0] = DP[1,0]; DP2[4,1] = DP[0,1] ; DP2[4,2] = DP[0,2]
|
|
#DP2[5,0] = DP[1,0]; DP2[5,1] = DP[0,1] ; DP2[5,2] = DP[1,2]
|
|
#DP2[6,0] = DP[1,0]; DP2[6,1] = DP[1,1] ; DP2[6,2] = DP[0,2]
|
|
#P2[7,0] = DP[1,0]; DP2[7,1] = DP[1,1] ; DP2[7,2] = DP[1,2]
|
|
|
|
|
|
return [kmin,kmax,PP,DP]
|
|
|
|
if mode=='ky':
|
|
PC = [np.ceil(numt2/2),np.ceil(row/2)]
|
|
PP = np.zeros([points,2])
|
|
DP = np.zeros([points-1,2])
|
|
for k in range(points):
|
|
PP[k,0] = numt2-(aa-1)*(k)
|
|
PP[k,1] = bb*(k)
|
|
|
|
if k<kmid:
|
|
DP[k,0] = PP[k,0] - PC[0]
|
|
DP[k,1] = PP[k,1] - PC[1]
|
|
if k>kmid:
|
|
DP[k-1,0] = PP[k,0] - PC[0]
|
|
DP[k-1,1] = PP[k,1] - PC[1]
|
|
|
|
kmax = int((PP[kmid,0] + PP[kmid-1,0])/2 )
|
|
kmin = int((PP[kmid,0] + PP[kmid+1,0])/2 )
|
|
return [kmin,kmax,PP,DP]
|
|
|
|
def SpreadPoint3D(M,R,sdep):
|
|
|
|
[row,col,dep,numt2] = M.shape
|
|
PS = np.zeros([row,col,dep,numt2],dtype=complex)
|
|
inx = 0
|
|
iny = 0
|
|
|
|
for k in range(np.mod(inx,R),row,R):
|
|
for ss in range(np.mod(iny,R),col,R):
|
|
PS[k,ss,:,:] = 1
|
|
iny = iny + 1
|
|
inx = inx + 1
|
|
|
|
|
|
for k in range(numt2):
|
|
PS[:,:,:,k] = np.fft.ifftn(PS[:,:,:,k])
|
|
PS[:,:,:,k] = np.fft.fftshift(PS[:,:,:,k])
|
|
|
|
|
|
SPREAD = PS[:,:,sdep,:]
|
|
SPREAD = np.fft.ifft(SPREAD,axis=2)
|
|
SPREAD = np.fft.fftshift(SPREAD,axes=2)
|
|
|
|
return SPREAD
|
|
|
|
def SpreadPoint(M,R,scol):
|
|
|
|
[row,col,numt2] = M.shape
|
|
PS = np.zeros([row,col,numt2],dtype=complex)
|
|
inx = 0
|
|
|
|
for l in range(0,numt2):
|
|
for k in range(np.mod(inx,R),row,R):
|
|
PS[k,:,l] = 1
|
|
inx = inx + 1
|
|
|
|
#PS = 1*(M!=0)
|
|
#PS = 0*M + 1
|
|
#SPREAD = KTT(PS,0)
|
|
|
|
for k in range(numt2):
|
|
PS[:,:,k] = np.fft.ifft2(PS[:,:,k])
|
|
PS[:,:,k] = np.fft.fftshift(PS[:,:,k])
|
|
|
|
|
|
SPREAD = PS[:,scol,:]
|
|
SPREAD = np.fft.ifft(SPREAD,axis=1)
|
|
SPREAD = np.fft.fftshift(SPREAD,axes=1)
|
|
|
|
return SPREAD
|
|
|
|
def ConvolSP(M1,M2):
|
|
M2 = M2[::-1,::-1]
|
|
M3 = sc.signal.convolve2d(M1,M2, boundary='wrap', mode='same')
|
|
return M3
|
|
|
|
def KTBLASTMETHOD_4D_kxky(ITOT,R,mode):
|
|
|
|
|
|
###################################################################
|
|
# Training Stage #
|
|
###################################################################
|
|
[row,col,dep,numt2] = ITOT.shape
|
|
# INPUT PARAMETERS
|
|
iteshort = 1
|
|
tetest = int(dep/2)
|
|
numt = int(numt2)
|
|
Dyy = int(row*0.1)
|
|
rmid = int(row/2)
|
|
cmid = int(col/2)
|
|
|
|
TKdata = np.zeros(ITOT.shape,dtype=complex)
|
|
UKdata = np.zeros(ITOT.shape,dtype=complex)
|
|
Kdata = np.zeros(ITOT.shape,dtype=complex)
|
|
Kdata_NEW0 = np.zeros(ITOT.shape,dtype=complex)
|
|
Kdata_NEW = np.zeros(ITOT.shape,dtype=complex)
|
|
KTBLAST0 = np.zeros(ITOT.shape,dtype=complex)
|
|
KTBLAST = np.zeros(ITOT.shape,dtype=complex)
|
|
|
|
|
|
for k in range(numt2):
|
|
# THE FULL KSPACE
|
|
Kdata[:,:,:,k] = np.fft.fftn(ITOT[:,:,:,k])
|
|
Kdata[:,:,:,k] = np.fft.fftshift(Kdata[:,:,:,k])
|
|
# UNDERSAMPLING STEP AND FILLED WITH ZEROS THE REST
|
|
UKdata[:,:,:,k] = UNDER(Kdata[:,:,:,k],mode,R,k)
|
|
|
|
# GENERATING THE TRAINING DATA WITH SUBSAMPLING the Center IN KX , KY
|
|
for k in range(numt):
|
|
TKdata[rmid-Dyy:rmid+Dyy+1,cmid-Dyy:cmid+Dyy+1,:,k] = Kdata[rmid-Dyy:rmid+Dyy+1,cmid-Dyy:cmid+Dyy+1,:,k]
|
|
|
|
[kmin,kmax,PP,DP] = get_points4D(row,col,dep,numt2,R,mode)
|
|
|
|
if iteshort==1:
|
|
print(PP)
|
|
print(DP)
|
|
print('range of k = ',kmin,kmax)
|
|
|
|
SPREAD = SpreadPoint3D(UKdata,R,tetest)
|
|
###################################################################
|
|
# RECONSTRUCTION #
|
|
###################################################################
|
|
ZE1 = iteshort + (tetest-1)*(iteshort)
|
|
ZE2 = (tetest+1)*(iteshort) + (dep)*(1-iteshort)
|
|
|
|
for zi in range(ZE1,ZE2):
|
|
|
|
if rank==0:
|
|
print('4D KTBLAST: R = ' + str(R) + ' and z = ' + str(zi)+'/'+str(dep))
|
|
|
|
### CONSTRUCT THE REFERENCE M_TRAINING
|
|
B2 = KTT3D(TKdata,zi)
|
|
B2 = FilteringHigh(B2,0.3)
|
|
M2 = 4*np.abs(B2)**2
|
|
#M2 = GetSymmetric(M2)
|
|
### INTERPOLATE IF NUMT<NUMT2 IS REQUIRED
|
|
if numt<numt2:
|
|
M2 = InterpolateM(M2,numt2)
|
|
#M2 = GetSymmetric(M2)
|
|
###################################################################
|
|
# Adquisition Stage #
|
|
###################################################################
|
|
VLund = KTT3D(UKdata,zi)
|
|
VLref = KTT3D(Kdata,zi)
|
|
VLnew = np.zeros(VLund.shape,dtype=complex)
|
|
|
|
|
|
#for k in range(kmin*0+12,kmax*0+13):
|
|
for k in range(kmin,kmax):
|
|
#for k in range(0,numt2):
|
|
for l in range(row):
|
|
for cc in range(col):
|
|
PEA = EveryAliased3D2(k,l,cc,PP,numt2,row,col,VLnew,R)
|
|
NAA = PEA.shape[1]
|
|
Mvec = np.zeros([1,NAA],dtype=complex)
|
|
un = np.ones([1,NAA],dtype=complex)
|
|
Mvec[0,:] = M2[PEA[1,:],PEA[2,:],PEA[0,:]]
|
|
ralia = NAA*VLund[l,cc,k]
|
|
MDIAG = np.diagflat(Mvec)
|
|
rnew = np.transpose(np.inner(un,MDIAG))/np.sum(np.inner(un,MDIAG))*ralia
|
|
VLnew[PEA[1,:],PEA[2,:],PEA[0,:]] = rnew[:,0]
|
|
#VLnew[PEA[1,:],PEA[2,:],PEA[0,:]] += 1
|
|
|
|
|
|
KTBLAST[:,:,zi,:] = IKTT3D(VLnew)
|
|
|
|
|
|
KTBLAST = np.fft.ifftshift(KTBLAST,axes=3)
|
|
|
|
if iteshort==1:
|
|
D0 = np.abs(M2)
|
|
D1 = np.abs(VLund)
|
|
D2 = np.abs(VLnew)
|
|
D3 = np.abs(VLref)
|
|
return [D0,D1,D2,D3]
|
|
|
|
if iteshort==0:
|
|
return KTBLAST
|
|
|
|
def KTBLASTMETHOD_4D_ky(ITOT,R,mode):
|
|
|
|
###################################################################
|
|
# Training Stage #
|
|
###################################################################
|
|
[row,col,dep,numt2] = ITOT.shape
|
|
# INPUT PARAMETERS
|
|
iteshort = 0
|
|
tetest = int(col/2)
|
|
zetest = int(3*dep/5)
|
|
numt = int(numt2/1)
|
|
Dyy = int(row*0.1)
|
|
rmid = int(row/2)
|
|
cmid = int(col/2)
|
|
|
|
TKdata = np.zeros(ITOT.shape,dtype=complex)
|
|
UKdata = np.zeros(ITOT.shape,dtype=complex)
|
|
Kdata = np.zeros(ITOT.shape,dtype=complex)
|
|
KTBLAST0 = np.zeros(ITOT.shape,dtype=complex)
|
|
KTBLAST = np.zeros(ITOT.shape,dtype=complex)
|
|
|
|
|
|
for k in range(numt2):
|
|
# THE FULL KSPACE
|
|
Kdata[:,:,:,k] = np.fft.fft2(ITOT[:,:,:,k], axes=(0,1))
|
|
Kdata[:,:,:,k] = np.fft.fftshift(Kdata[:,:,:,k])
|
|
# UNDERSAMPLING STEP AND FILLED WITH ZEROS THE REST
|
|
UKdata[:,:,:,k] = UNDER(Kdata[:,:,:,k],mode,R,k)
|
|
|
|
|
|
# GENERATING THE TRAINING DATA WITH ONLY SUBSAMPLING IN KY
|
|
for k in range(numt):
|
|
TKdata[rmid-Dyy:rmid+Dyy+1,:,:,k] = Kdata[rmid-Dyy:rmid+Dyy+1,:,:,k]
|
|
|
|
[kmin,kmax,PP,DP] = get_points4D(row,col,dep,numt2,R,mode)
|
|
|
|
if iteshort==1:
|
|
print(PP)
|
|
print(DP)
|
|
print('range of y = ',kmin,kmax)
|
|
|
|
|
|
#SPREAD = SpreadPoint(UKdata,R,tetest)
|
|
###################################################################
|
|
# RECONSTRUCTION #
|
|
###################################################################
|
|
TE1 = iteshort + (tetest-1)*(iteshort)
|
|
TE2 = (tetest+1)*(iteshort) + (col)*(1-iteshort)
|
|
ZE1 = iteshort + (zetest-1)*(iteshort)
|
|
ZE2 = (zetest+1)*(iteshort) + (dep)*(1-iteshort)
|
|
|
|
for zi in range(ZE1,ZE2):
|
|
if rank==0:
|
|
print('4D KTBLAST: z = ',zi)
|
|
|
|
for te in range(TE1,TE2):
|
|
|
|
### CONSTRUCT THE REFERENCE M_TRAINING
|
|
B2 = KTT(TKdata[:,:,zi,:],te)
|
|
B2 = FilteringHigh(B2,0.3)
|
|
M2 = 4*np.abs(B2)**2
|
|
M2 = GetSymmetric(M2)
|
|
### INTERPOLATE IF NUMT<NUMT2 IS REQUIRED
|
|
if numt<numt2:
|
|
M2 = InterpolateM(M2,numt2)
|
|
M2 = GetSymmetric(M2)
|
|
###################################################################
|
|
# Adquisition Stage #
|
|
###################################################################
|
|
VLund = KTT(UKdata[:,:,zi,:],te)
|
|
VLref = KTT(Kdata[:,:,zi,:],te)
|
|
VLnew = np.zeros(VLund.shape,dtype=complex)
|
|
|
|
for k in range(kmin,kmax):
|
|
for l in range(row):
|
|
PEA = EveryAliased(k,l,DP,numt2,row,VLnew,R,1)
|
|
NAA = PEA.shape[1]
|
|
Mvec = np.zeros([1,NAA],dtype=complex)
|
|
un = np.ones([1,NAA],dtype=complex)
|
|
Mvec[0,:] = M2[PEA[1,:],PEA[0,:]]
|
|
ralia = NAA*VLund[l,k]
|
|
MDIAG = np.diagflat(Mvec)
|
|
rnew = np.transpose(np.inner(un,MDIAG))/np.sum(np.inner(un,MDIAG))*ralia
|
|
VLnew[PEA[1,:],PEA[0,:]] = rnew[:,0]
|
|
|
|
|
|
KTBLAST[:,te,zi,:] = IKTT(VLnew)
|
|
|
|
|
|
KTBLAST = np.fft.ifftshift(KTBLAST,axes=2)
|
|
|
|
|
|
if iteshort==1:
|
|
D0 = np.abs(M2)
|
|
D1 = np.abs(VLund)
|
|
D2 = np.abs(VLnew)
|
|
D3 = np.abs(VLref)
|
|
return [D0,D1,D2,D3]
|
|
|
|
if iteshort==0:
|
|
return KTBLAST
|
|
|
|
def phase_contrast(M1,M0,VENC,scantype='0G'):
|
|
param = 1
|
|
if scantype=='-G+G':
|
|
param = 0.5
|
|
return VENC*param*(np.angle(M1) - np.angle(M0))/np.pi
|
|
|
|
def GenerateMagnetization(Sq,VENC,noise,scantype='0G'):
|
|
# MRI PARAMETERS
|
|
gamma = 267.513e6 # rad/Tesla/sec Gyromagnetic ratio for H nuclei
|
|
B0 = 1.5 # Tesla Magnetic Field Strenght
|
|
TE = 5e-3 # Echo-time
|
|
M1 = np.pi/(gamma*VENC)
|
|
|
|
PHASE0 = np.zeros(Sq.shape)
|
|
PHASE1 = np.zeros(Sq.shape)
|
|
RHO0 = np.zeros(Sq.shape,dtype=complex)
|
|
RHO1 = np.zeros(Sq.shape,dtype=complex)
|
|
# THE K DATA
|
|
KRHO0 = np.zeros(Sq.shape,dtype=complex)
|
|
KRHO1 = np.zeros(Sq.shape,dtype=complex)
|
|
|
|
if np.ndim(Sq)==3:
|
|
[row,col,numt2] = Sq.shape
|
|
[X,Y] = np.meshgrid(np.linspace(0,col,col),np.linspace(0,row,row))
|
|
for k in range(numt2):
|
|
if noise:
|
|
Drho = np.random.normal(0,0.2,[row,col])
|
|
Drho2 = np.random.normal(0,0.2,[row,col])
|
|
else:
|
|
Drho = np.zeros([row,col])
|
|
Drho2 = np.zeros([row,col])
|
|
|
|
varPHASE0 = np.random.randint(-10,11,size=(row,col))*np.pi/180*(np.abs(Sq[:,:,k])<0.001) #Hugo's observation
|
|
modulus = 0.5 + 0.5*(np.abs(Sq[:,:,k])>0.001)
|
|
|
|
if scantype=='0G':
|
|
PHASE0[:,:,k] = (gamma*B0*TE+0.01*X)*(np.abs(Sq[:,:,k])>0.001) + 10*varPHASE0
|
|
PHASE1[:,:,k] = (gamma*B0*TE+0.01*X)*(np.abs(Sq[:,:,k])>0.001) + 10*varPHASE0 + np.pi*Sq[:,:,k]/VENC
|
|
|
|
if scantype=='-G+G':
|
|
PHASE0[:,:,k] = gamma*B0*TE*np.ones([row,col]) + 10*varPHASE0 - np.pi*Sq[:,:,k]/VENC
|
|
PHASE1[:,:,k] = gamma*B0*TE*np.ones([row,col]) + 10*varPHASE0 + np.pi*Sq[:,:,k]/VENC
|
|
|
|
RHO0[:,:,k] = modulus*np.cos(PHASE0[:,:,k]) + Drho + 1j*modulus*np.sin(PHASE0[:,:,k]) + 1j*Drho2
|
|
RHO1[:,:,k] = modulus*np.cos(PHASE1[:,:,k]) + Drho + 1j*modulus*np.sin(PHASE1[:,:,k]) + 1j*Drho2
|
|
|
|
|
|
if np.ndim(Sq)==4:
|
|
[row,col,dep,numt2] = Sq.shape
|
|
[X,Y,Z] = np.meshgrid(np.linspace(0,col,col),np.linspace(0,row,row),np.linspace(0,dep,dep))
|
|
|
|
for k in range(numt2):
|
|
|
|
if noise:
|
|
Drho = np.random.normal(0,0.2,[row,col,dep])
|
|
Drho2 = np.random.normal(0,0.2,[row,col,dep])
|
|
else:
|
|
Drho = np.zeros([row,col,dep])
|
|
Drho2 = np.zeros([row,col,dep])
|
|
|
|
varPHASE0 = np.random.randint(-10,11,size=(row,col,dep))*np.pi/180*(np.abs(Sq[:,:,:,k])<0.001)
|
|
modulus = 0.5 + 0.5*(np.abs(Sq[:,:,:,k])>0.001)
|
|
|
|
if scantype=='0G':
|
|
PHASE0[:,:,:,k] = (gamma*B0*TE+0.01*X)*(np.abs(Sq[:,:,:,k])>0.001) + 10*varPHASE0
|
|
PHASE1[:,:,:,k] = (gamma*B0*TE+0.01*X)*(np.abs(Sq[:,:,:,k])>0.001) + 10*varPHASE0 + np.pi*Sq[:,:,:,k]/VENC
|
|
|
|
if scantype=='-G+G':
|
|
PHASE0[:,:,:,k] = gamma*B0*TE*np.ones([row,col,dep]) + varPHASE0 - np.pi*Sq[:,:,:,k]/VENC
|
|
PHASE1[:,:,:,k] = gamma*B0*TE*np.ones([row,col,dep]) + varPHASE0 + np.pi*Sq[:,:,:,k]/VENC
|
|
|
|
RHO0[:,:,:,k] = modulus*np.cos(PHASE0[:,:,:,k]) + Drho + 1j*modulus*np.sin(PHASE0[:,:,:,k]) + 1j*Drho2
|
|
RHO1[:,:,:,k] = modulus*np.cos(PHASE1[:,:,:,k]) + Drho + 1j*modulus*np.sin(PHASE1[:,:,:,k]) + 1j*Drho2
|
|
|
|
|
|
|
|
|
|
return [RHO0,RHO1]
|
|
|
|
def undersampling(Sqx,Sqy,Sqz,options,savepath):
|
|
|
|
R = options['kt-BLAST']['R']
|
|
mode = options['kt-BLAST']['mode']
|
|
transpose = True
|
|
|
|
for r in R:
|
|
|
|
if rank==0:
|
|
print('Using Acceleration Factor R = ' + str(r))
|
|
print('Component x of M0')
|
|
|
|
[M0,M1] = GenerateMagnetization(Sqx,options['kt-BLAST']['VENC'],options['kt-BLAST']['noise'],scantype='0G')
|
|
if transpose:
|
|
M0 = M0.transpose((0,2,1,3))
|
|
M1 = M1.transpose((0,2,1,3))
|
|
|
|
if mode=='ky':
|
|
M0_kt = KTBLASTMETHOD_4D_ky(M0,r,mode)
|
|
if mode=='kxky':
|
|
M0_kt = KTBLASTMETHOD_4D_kxky(M0,r,mode)
|
|
|
|
if rank==0:
|
|
print('\n Component x of M1')
|
|
|
|
if mode=='ky':
|
|
M1_kt = KTBLASTMETHOD_4D_ky(M1,r,mode)
|
|
if mode=='kxky':
|
|
M1_kt = KTBLASTMETHOD_4D_kxky(M1,r,mode)
|
|
|
|
|
|
Sqx_kt = phase_contrast(M1_kt,M0_kt,options['kt-BLAST']['VENC'],scantype='0G')
|
|
|
|
del M0,M1
|
|
del M0_kt, M1_kt
|
|
|
|
[M0,M1] = GenerateMagnetization(Sqy,options['kt-BLAST']['VENC'],options['kt-BLAST']['noise'],scantype='0G')
|
|
if transpose:
|
|
M0 = M0.transpose((0,2,1,3))
|
|
M1 = M1.transpose((0,2,1,3))
|
|
if rank==0:
|
|
print('\n Component y of M0')
|
|
|
|
if mode=='ky':
|
|
M0_kt = KTBLASTMETHOD_4D_ky(M0,r,mode)
|
|
if mode=='kxky':
|
|
M0_kt = KTBLASTMETHOD_4D_kxky(M0,r,mode)
|
|
|
|
|
|
if rank==0:
|
|
print('\n Component y of M1')
|
|
|
|
if mode=='ky':
|
|
M1_kt = KTBLASTMETHOD_4D_ky(M1,r,mode)
|
|
if mode=='kxky':
|
|
M1_kt = KTBLASTMETHOD_4D_kxky(M1,r,mode)
|
|
|
|
Sqy_kt = phase_contrast(M1_kt,M0_kt,options['kt-BLAST']['VENC'],scantype='0G')
|
|
|
|
del M0,M1
|
|
del M0_kt, M1_kt
|
|
|
|
[M0,M1] = GenerateMagnetization(Sqz,options['kt-BLAST']['VENC'],options['kt-BLAST']['noise'],scantype='0G')
|
|
if transpose:
|
|
M0 = M0.transpose((0,2,1,3))
|
|
M1 = M1.transpose((0,2,1,3))
|
|
if rank==0:
|
|
print('\n Component z of M0')
|
|
|
|
if mode=='ky':
|
|
M0_kt = KTBLASTMETHOD_4D_ky(M0,r,mode)
|
|
|
|
if mode=='kxky':
|
|
M0_kt = KTBLASTMETHOD_4D_kxky(M0,r,mode)
|
|
|
|
if rank==0:
|
|
print('\n Component z of M1')
|
|
|
|
if mode=='ky':
|
|
M1_kt = KTBLASTMETHOD_4D_ky(M1,r,mode)
|
|
if mode=='kxky':
|
|
M1_kt = KTBLASTMETHOD_4D_kxky(M1,r,mode)
|
|
|
|
if rank==0:
|
|
print(' ')
|
|
|
|
Sqz_kt = phase_contrast(M1_kt,M0_kt,options['kt-BLAST']['VENC'],scantype='0G')
|
|
|
|
|
|
if transpose:
|
|
Sqx_kt = Sqx_kt.transpose((0,2,1,3))
|
|
Sqy_kt = Sqy_kt.transpose((0,2,1,3))
|
|
Sqz_kt = Sqz_kt.transpose((0,2,1,3))
|
|
|
|
|
|
if options['kt-BLAST']['save']:
|
|
if rank==0:
|
|
print('saving the sequences in ' + savepath)
|
|
seqname = options['kt-BLAST']['name'] +'_R' + str(r) + '.npz'
|
|
print('sequence name: ' + seqname)
|
|
np.savez_compressed( savepath + seqname, x=Sqx_kt, y=Sqy_kt,z=Sqz_kt)
|
|
|
|
del Sqx_kt,Sqy_kt,Sqz_kt
|
|
|
|
|
|
|
|
|