#### 706 lines 25 KiB Python Raw Normal View History

 2020-01-17 16:24:10 +01:00 `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()` ``` ``` ``` ``` `# COMPRESSED SENSING: LINEAR BREGMAN METHOD` `# Translated and adapted into python from tinycs` `#` `# *tinycs* is a minimal compressed sensing (CS) toolkit designed` `# to allow MR imaging scientists to design undersampled` `# acquisitions and reconstruct the resulting data with CS without` `# needing to be a CS expert.` `# ` `# The Cartesian reconstruction is based on the split Bregman` `# code written by Tom Goldstein, originally available here:` `# ` ``` ``` ``` ``` `def pdf(k,kw,klo,q):` ` ` ` p = (np.abs(k)/kw)**(-q)` ` p[np.where(k==0)] = 0` ` p[np.where(np.abs(k)<=kw)] = 1` ` p[np.where(k=norm:` ` break` ` ` ` P = np.fft.fftshift(P)` ` ` ` ` ` #if np.mod(n,2)!=0:` ` # P = np.concatenate(([1],P),axis=None)` ` ` ` ` ``` ``` ` return P` ``` ``` `def mask_pdf_2d(dims,norm,q,pf):` ` ` ` nz = dims[1]` ` ny = dims[0]` ` yc = round(ny/2)` ` zc = round(nz/2)` ` rmax = np.sqrt((ny-yc)**2 + (nz-zc)**2)` ` [Z,Y] = np.meshgrid(np.arange(0,nz),np.arange(0,ny))` ` RR = np.sqrt( (Y-yc)**2 + (Z-zc)**2)` ` Z = np.abs(Z - nz/2 - 0.5)` ` Y = np.abs(Y - ny/2 - 0.5)` ` ` ` ` ` for rw in range(1,int(rmax)+1):` ` P = np.ones([ny,nz])/pf` ` C = np.logical_and( Z <= rw , Y <= rw)` ` W = np.logical_or( Z > rw , Y > rw)` ` P[W] = (RR[W]/rw)**(-q)` ` if np.sum(P) >= norm:` ` break ` ` ` ` ` ` ` ` return [P,C]` ``` ``` `def GeneratePattern(dim,R):` ` ` ` # 3D CASE` ` if np.size(dim)==3:` ` ` ` nro = dim[0]` ` npe = dim[1]` ` nacq = round(npe/R)` ` q = 1` ` pf = 1` ` P = mask_pdf_1d(npe, nacq, q, pf)` ` while True:` ` M = np.random.rand(npe)` ` M = 1*(M<=P)` ` if np.sum(M)==nacq:` ` break` ` # remove partial Fourier plane and compensate sampling density` ` M = M!=0` ` M = np.tile(M,[nro,1]);` ` #M = M.T` ``` ``` ` # 4D CASE` ` if np.size(dim)==4:` ` ` ` nro = dim[0]` ` npe1 = dim[1]` ` npe2 = dim[2]` ` nacq = round(npe1*npe2/R)` ` q = 1` ` pf = 1` ` [P,C] = mask_pdf_2d([npe1,npe2], nacq, q, pf)` ` RR = np.random.rand(npe1,npe2)` ` M = (RR <= P)` ` nchosen = np.sum(M)` ` if nchosen > nacq: # Correct for inexact number chosen` ` #outerOn = np.logical_and( M , P!=1 )` ` outerOn = np.where((M)*(P!=1))` ` numToFlip = nchosen-nacq` ` idxs = np.random.permutation(outerOn[0].size)` ` idxx = outerOn[0][idxs[0:numToFlip]]` ` idxy = outerOn[1][idxs[0:numToFlip]]` ` M[idxx,idxy] = False` ` ` ` elif nchosen < nacq:` ` outerOff = np.where(~M)` ` idxs = np.random.permutation(outerOff[0].size)` ` numToFlip = nacq - nchosen` ` idxx = outerOff[0][idxs[0:numToFlip]]` ` idxy = outerOff[1][idxs[0:numToFlip]]` ` M[idxx,idxy] = True` ` ` ` ` ` ` ` ` ` M = np.rollaxis(np.tile(np.rollaxis(M,1),[nro,1,1]),2)` ` M = np.fft.ifftshift(M)` ` M = M.transpose((1,0,2))` ` ` ``` ``` ` return M` ``` ``` `def get_norm_factor(MASK,uu):` ` UM = MASK==1` ` return UM.shape[0]/LA.norm(uu)` ``` ``` `def Dxyzt(X):` ` ` ` if np.ndim(X)==3:` ` dd0 = X[:,:,0]` ` dd1 = X[:,:,1]` ` DA = dd0 - np.vstack((dd0[1::,:],dd0[0,:])) ` ` DB = dd1 - np.hstack((dd1[:,1::],dd1[:,0:1])) ` ` ` ` return DA + DB` ``` ``` ` if np.ndim(X)==4:` ` dd0 = X[:,:,:,0]` ` dd1 = X[:,:,:,1]` ` dd2 = X[:,:,:,2]` ` ` ` DA = dd0 - np.vstack((dd0[1::,:,:],dd0[0,:,:][np.newaxis,:,:])) ` ` DB = dd1 - np.hstack((dd1[:,1::,:],dd1[:,0,:][:,np.newaxis,:])) ` ` DC = dd2 - np.dstack((dd2[:,:,1::],dd2[:,:,0][:,:,np.newaxis]))` ` ` ` return DA + DB + DC` ``` ``` `def Dxyz(u):` ` ` ` if np.ndim(u)==2:` ` ` ` dx = u[:,:]- np.vstack((u[-1,:],u[0:-1,:])) ` ` dy = u[:,:]- np.hstack((u[:,-1:],u[:,0:-1])) ` ` D = np.zeros([dx.shape[0],dx.shape[1],2],dtype=complex)` ` D[:,:,0] = dx` ` D[:,:,1] = dy` ` ` ` return D` ``` ``` ` if np.ndim(u)==3:` ` ` ` dx = u[:,:,:]- np.vstack((u[-1,:,:][np.newaxis,:,:],u[0:-1,:,:])) ` ` dy = u[:,:,:]- np.hstack((u[:,-1,:][:,np.newaxis,:],u[:,0:-1,:])) ` ` dz = u[:,:,:]- np.dstack((u[:,:,-1][:,:,np.newaxis],u[:,:,0:-1])) ` ` ` ` D = np.zeros([dx.shape[0],dx.shape[1],dx.shape[2],3],dtype=complex)` ` ` ` D[:,:,:,0] = dx` ` D[:,:,:,1] = dy` ` D[:,:,:,2] = dz` ` ` ` return D` ``` ``` `def shrink(X,pgam):` ` p = 1` ` s = np.abs(X)` ` tt = pgam/(s)**(1-p)` ` # t = pgam/np.sqrt(s)` ` ss = s-tt` ` ss = ss*(ss>0)` ` s = s + 1*(s0.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['cs']['R']` ` ` ` for r in R:` ` ` ` if rank==0:` ` print('Using Acceleration Factor R = ' + str(r))` ` print('Component x of M0')` ` ` ` [M0,M1] = GenerateMagnetization(Sqx,options['cs']['VENC'],options['cs']['noise'])` ` ` ``` ``` ` print('\n Component x of M0')` ` M0_cs = CSMETHOD(M0,r)` ` print('\n Component x of M1')` ` M1_cs = CSMETHOD(M1,r)` ``` ``` ` Sqx_cs = phase_contrast(M1_cs,M0_cs,options['cs']['VENC'])` ` del M0,M1` ` del M0_cs, M1_cs` ` ` ` [M0,M1] = GenerateMagnetization(Sqy,options['cs']['VENC'],options['cs']['noise'])` ` ` ``` ``` ` print('\n Component y of M0')` ` M0_cs = CSMETHOD(M0,r)` ` print('\n Component y of M1')` ` M1_cs = CSMETHOD(M1,r)` ` ` ``` ``` ` Sqy_cs = phase_contrast(M1_cs,M0_cs,options['cs']['VENC'])` ` ` ` del M0,M1` ` del M0_cs, M1_cs` ` ` ` [M0,M1] = GenerateMagnetization(Sqz,options['cs']['VENC'],options['cs']['noise'])` ` ` ` if rank==0:` ` print('\n Component z of M0')` ` M0_cs = CSMETHOD(M0,r)` ` if rank==0:` ` print('\n Component z of M1')` ` M1_cs = CSMETHOD(M1,r)` ` if rank==0:` ` print(' ')` ` ` ` Sqz_cs = phase_contrast(M1_cs,M0_cs,options['cs']['VENC']) ` ` ` ` ` ` if rank==0:` ` print('saving the sequences in ' + savepath)` ` seqname = options['cs']['name'] +'_R' + str(r) + '.npz'` ` print('sequence name: ' + seqname)` ` np.savez_compressed( savepath + seqname, x=Sqx_cs, y=Sqy_cs,z=Sqz_cs)` ` ` ` del Sqx_cs,Sqy_cs,Sqz_cs` ` ` `def undersampling_peakpv(Sqx,Sqy,Sqz,options,R):` ` ` ` Sqx_cs = {}` ` Sqy_cs = {}` ` Sqz_cs = {}` ` [Mx0,Mx1] = GenerateMagnetization(Sqx,options['cs']['VENC'],options['cs']['noise'],scantype='0G')` ` [My0,My1] = GenerateMagnetization(Sqy,options['cs']['VENC'],options['cs']['noise'],scantype='0G')` ` [Mz0,Mz1] = GenerateMagnetization(Sqz,options['cs']['VENC'],options['cs']['noise'],scantype='0G')` ` ` ``` ``` ` Mx0_cs = CSMETHOD(Mx0,R)` ` Mx1_cs = CSMETHOD(Mx1,R)` ` My0_cs = CSMETHOD(My0,R)` ` My1_cs = CSMETHOD(My1,R)` ` Mz0_cs = CSMETHOD(Mz0,R)` ` Mz1_cs = CSMETHOD(Mz1,R)` ``` ``` ` Sqx_cs = phase_contrast(Mx1_cs,Mx0_cs,options['cs']['VENC'],scantype='0G') ` ` Sqy_cs = phase_contrast(My1_cs,My0_cs,options['cs']['VENC'],scantype='0G') ` ` Sqz_cs = phase_contrast(Mz1_cs,Mz0_cs,options['cs']['VENC'],scantype='0G') ` ` ` ` ` ` ` ` return [Sqx_cs,Sqy_cs,Sqz_cs]` ` ` `def undersampling_short(Mx,My,Mz,options):` ` ` ` R = options['cs']['R']` ` savepath = options['cs']['savepath']` ``` ``` ``` ``` ` R_SENSE = 1` ` if 'R_SENSE' in options['cs']:` ` R_SENSE = options['cs']['R_SENSE'][0]` ``` ``` ` for r in R: ` ` if rank==0:` ` print('Using Acceleration Factor R = ' + str(r))` ` ` ``` ``` ` if R_SENSE==2: ` ` [MxS0_cs,MxS1_cs] = CSMETHOD_SENSE(Mx,r,2)` ` [MyS0_cs,MyS1_cs] = CSMETHOD_SENSE(My,r,2)` ` [MzS0_cs,MzS1_cs] = CSMETHOD_SENSE(Mz,r,2)` ` if rank==0:` ` print('saving the sequences in ' + savepath)` ` seqname_s0 = options['cs']['name'] +'S0_R' + str(r) + '.npz'` ` seqname_s1 = options['cs']['name'] +'S1_R' + str(r) + '.npz'` ` print('sequence name: ' + seqname_s0)` ` np.savez_compressed( savepath + seqname_s0, x=MxS0_cs, y=MyS0_cs,z=MzS0_cs)` ` print('sequence name: ' + seqname_s1)` ` np.savez_compressed( savepath + seqname_s1, x=MxS1_cs, y=MyS1_cs,z=MzS1_cs)` ` del MxS0_cs, MyS0_cs, MzS0_cs` ` del MxS1_cs, MyS1_cs, MzS1_cs` ` elif R_SENSE==1:` ` Mx_cs = CSMETHOD(Mx,r)` ` My_cs = CSMETHOD(My,r)` ` Mz_cs = CSMETHOD(Mz,r)` ` if rank==0:` ` print('saving the sequences in ' + savepath)` ` seqname = options['cs']['name'] +'_R' + str(r) + '.npz'` ` print('sequence name: ' + seqname)` ` np.savez_compressed( savepath + seqname, x=Mx_cs, y=My_cs,z=Mz_cs)` ` del Mx_cs,My_cs,Mz_cs` ` else:` ` raise Exception('Only implemented for 2-fold SENSE!!')` ``` ``` ``` ``` ``` ``` ``` ``` ``` ``` ``` ``` `# THE END` ``` ``` ``` ``` ``` ```