From 2da253f27824f9556f343d0076fb9184ae7f4833 Mon Sep 17 00:00:00 2001 From: jeremias Date: Fri, 17 Jan 2020 16:24:10 +0100 Subject: [PATCH] codes copied --- codes/.vscode/launch.json | 15 + codes/.vscode/tasks.json | 12 + codes/CS.py | 705 ++++++++ codes/Graphics.py | 1581 +++++++++++++++++ codes/MATLAB/createU.m | 57 + codes/MATLAB/leo/CREATE_MESH.m | 14 + codes/MATLAB/leo/maskFEM.m | 19 + codes/MATLAB/leo/meshStructTess.m | 169 ++ codes/MATLAB/leo/writemesh.m | 97 ++ codes/MATLAB/load_dicom.m | 126 ++ codes/MRI.py | 1936 +++++++++++++++++++++ codes/PostCheck.py | 1072 ++++++++++++ codes/SENSE.py | 115 ++ codes/__pycache__/CS.cpython-36.pyc | Bin 0 -> 15426 bytes codes/__pycache__/Graphics.cpython-36.pyc | Bin 0 -> 36990 bytes codes/__pycache__/MRI.cpython-36.pyc | Bin 0 -> 49504 bytes codes/__pycache__/SENSE.cpython-36.pyc | Bin 0 -> 3377 bytes codes/__pycache__/ktBLAST.cpython-36.pyc | Bin 0 -> 19395 bytes codes/cfd_mono.py | 327 ++++ codes/ktBLAST.py | 870 +++++++++ codes/mesh_generator.py | 71 + 21 files changed, 7186 insertions(+) create mode 100644 codes/.vscode/launch.json create mode 100644 codes/.vscode/tasks.json create mode 100644 codes/CS.py create mode 100644 codes/Graphics.py create mode 100644 codes/MATLAB/createU.m create mode 100755 codes/MATLAB/leo/CREATE_MESH.m create mode 100755 codes/MATLAB/leo/maskFEM.m create mode 100755 codes/MATLAB/leo/meshStructTess.m create mode 100755 codes/MATLAB/leo/writemesh.m create mode 100644 codes/MATLAB/load_dicom.m create mode 100644 codes/MRI.py create mode 100644 codes/PostCheck.py create mode 100644 codes/SENSE.py create mode 100644 codes/__pycache__/CS.cpython-36.pyc create mode 100644 codes/__pycache__/Graphics.cpython-36.pyc create mode 100644 codes/__pycache__/MRI.cpython-36.pyc create mode 100644 codes/__pycache__/SENSE.cpython-36.pyc create mode 100644 codes/__pycache__/ktBLAST.cpython-36.pyc create mode 100644 codes/cfd_mono.py create mode 100644 codes/ktBLAST.py create mode 100755 codes/mesh_generator.py diff --git a/codes/.vscode/launch.json b/codes/.vscode/launch.json new file mode 100644 index 0000000..17e15f2 --- /dev/null +++ b/codes/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal" + } + ] +} \ No newline at end of file diff --git a/codes/.vscode/tasks.json b/codes/.vscode/tasks.json new file mode 100644 index 0000000..6c28385 --- /dev/null +++ b/codes/.vscode/tasks.json @@ -0,0 +1,12 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "echo", + "type": "shell", + "command": "echo Hello" + } + ] +} \ No newline at end of file diff --git a/codes/CS.py b/codes/CS.py new file mode 100644 index 0000000..1d0d2bd --- /dev/null +++ b/codes/CS.py @@ -0,0 +1,705 @@ +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 + + + diff --git a/codes/Graphics.py b/codes/Graphics.py new file mode 100644 index 0000000..03eb121 --- /dev/null +++ b/codes/Graphics.py @@ -0,0 +1,1581 @@ +import h5py +from dolfin import * +import numpy as np +from matplotlib import pyplot as plt +import scipy as sc +import scipy.io as sio +from mpl_toolkits.mplot3d import Axes3D +from mpl_toolkits.mplot3d import proj3d +import os, sys +import csv +from common import inout +import time + +from matplotlib import rc +#rc('font',**{'family':'sans-serif','sans-serif':['Helvetica']}) +rc('text', usetex=True) + + +def MATmedical(path): + + + datatype = None + + if 'ODV' in path: + datatype = 'odv' + print('The DATA file has the next structure: [x,y,z,coil,CardiacPhase,gradient,NSA] where x \ + and y are the spatial dimensions for the image. z is one because is only one slice. Coil is \ + the number of coils (5), CardiacPhase is the time dimension. Gradient is the number of gradients used in the \ + adquisition (2). NSA is the number of signal average.') + + if 'Phantom' in path: + datatype = 'cib_phantom' + #print('CIB phantom data which contains magnitude and velocity measurements.') + + + if not datatype=='cib_phantom': + STRUC = sio.loadmat(path) + DAT0 = STRUC['data'] + if datatype=='odv': + KDAT0 = STRUC['kdata'] + [row,col,coil,numt2,p4,p5] = DAT0.shape + else: + KDAT0 = STRUC['k_data'] + [row,col,slicesel,coil,numt2,p4,p5] = DAT0.shape + + + z0 = 0 + NSA = 0 + coilnum = 3 + + DAT1 = np.zeros([row,col,numt2],dtype=complex) + DAT2 = np.zeros([row,col,numt2],dtype=complex) + KDAT1 = np.zeros([row,col,numt2],dtype=complex) + KDAT2 = np.zeros([row,col,numt2],dtype=complex) + + if datatype=='odv': + for k in range(numt2): + DAT1[:,:,k] = DAT0[:,:,coilnum,k,0,NSA] + DAT2[:,:,k] = DAT0[:,:,coilnum,k,1,NSA] + KDAT1[:,:,k] = KDAT0[:,:,coilnum,k,0,NSA] + KDAT2[:,:,k] = KDAT0[:,:,coilnum,k,1,NSA] + + return [DAT1,DAT2,KDAT1,KDAT2] + else: + + UK1 = np.zeros([row,col,numt2],dtype=complex) + UK2 = np.zeros([row,col,numt2],dtype=complex) + + for k in range(numt2): + DAT1[:,:,k] = DAT0[:,:,z0,coilnum,k,0,NSA] + DAT2[:,:,k] = DAT0[:,:,z0,coilnum,k,1,NSA] + KDAT1[:,:,k] = KDAT0[:,:,z0,coilnum,k,0,NSA] + KDAT2[:,:,k] = KDAT0[:,:,z0,coilnum,k,1,NSA] + UK1[:,:,k] = np.fft.fftshift(np.fft.fft2(DAT1[:,:,k])) + UK2[:,:,k] = np.fft.fftshift(np.fft.fft2(DAT2[:,:,k])) + + return [DAT1,DAT2,KDAT1,KDAT2] + + elif datatype=='cib_phantom': + + lp = len(path) + for k in range(lp): + if path[lp-1-k]=='/': + name_var = path[lp-k:lp] + break + + name_var = name_var.replace('.mat','') + + if name_var in ['VENC','Segmented_Aorta','voxel_MR']: + STRUC = sio.loadmat(path) + return STRUC[name_var] + else: + #import h5py + arrays = {} + f = h5py.File(path) + for k, v in f.items(): + arrays[k] = np.array(v) + + return arrays[name_var].transpose((1,2,3,0)) + +def Plot_Inlet(): + ''' To Show the flow given at the inlet in the FEM simulation ''' + + Tf = 0.9 + dt = 0.0005 + t = np.linspace(0,Tf,Tf/dt) + U = 60 + Th = 0.37 + DOLFIN_PI = 3.1416 + y = U*np.sin(DOLFIN_PI*t/Th)*(t<=Th) + (Th0: + plt.ylim(ywin) + plt.xlim(xwin) + ax.set_aspect('auto') + + plt.xticks([]) + plt.yticks([]) + #plt.xlabel('$x$',Fontsize=20) + #plt.ylabel('$y$',Fontsize=20) + plt.title('phase ' + str(k)) + plt.show() + + if recorder: + plt.savefig('results/pictures/frame'+str(k),bbox_inches='tight') + + plt.pause(0.101) + plt.clf() + +def PrintSequence2(A,X,Y,Z,x,y,z): + + plt.ion() + fig = plt.figure(figsize=(7, 7), dpi=100) + ax = fig.add_subplot(1,1,1) + [row,col,dep] = A.shape + + + xi = np.linspace(np.min(x),np.max(x),row) + yi = np.linspace(np.min(y),np.max(y),col) + yi2 = np.min(yi) + np.max(yi) - yi + + from matplotlib.colors import LinearSegmentedColormap + basic_cols = ['#ff4e2b', '#000000', '#1893db'] + my_cmap = LinearSegmentedColormap.from_list('mycmap', basic_cols) + ccmap = mpl.cm.Spectral + + xt = x + yt = y + zt = z + yt2 = (np.min(y) + np.max(y)) - y + Dz = (np.max(z) - np.min(z))/dep + + def shiftedColorMap(cmap, start=0, midpoint=0.5, stop=1.0, name='shifted'): + ''' + Function to offset the "center" of a colormap. Useful for + data with a negative min and positive max and you want the + middle of the colormap's dynamic range to be at zero. + + Input + ----- + cmap : The matplotlib colormap to be altered + start : Offset from lowest point in the colormap's range. + Defaults to 0.0 (no lower offset). Should be between + 0.0 and `midpoint`. + midpoint : The new center of the colormap. Defaults to + 0.5 (no shift). Should be between 0.0 and 1.0. In + general, this should be 1 - vmax / (vmax + abs(vmin)) + For example if your data range from -15.0 to +5.0 and + you want the center of the colormap at 0.0, `midpoint` + should be set to 1 - 5/(5 + 15)) or 0.75 + stop : Offset from highest point in the colormap's range. + Defaults to 1.0 (no upper offset). Should be between + `midpoint` and 1.0. + ''' + + cdict = { + 'red': [], + 'green': [], + 'blue': [], + 'alpha': [] + } + + # regular index to compute the colors + reg_index = np.linspace(start, stop, 257) + + # shifted index to match the data + shift_index = np.hstack([ + np.linspace(0.0, midpoint, 128, endpoint=False), + np.linspace(midpoint, 1.0, 129, endpoint=True) + ]) + + for ri, si in zip(reg_index, shift_index): + r, g, b, a = cmap(ri) + + cdict['red'].append((si, r, r)) + cdict['green'].append((si, g, g)) + cdict['blue'].append((si, b, b)) + cdict['alpha'].append((si, a, a)) + + newcmap = mpl.colors.LinearSegmentedColormap(name, cdict) + plt.register_cmap(cmap=newcmap) + + return newcmap + + ccmap = mpl.cm.Spectral + shifted_ccmap = shiftedColorMap(ccmap, midpoint=0.75, name='shifted') + + for k in range(dep): + + zmin = np.min(z) + k*Dz + zmax = zmin + Dz + xs = np.array([]) + ys = np.array([]) + zs = np.array([]) + + for j in range(z.size): + if z[j]>= zmin and z[j] 1: + if os.path.exists(sys.argv[1]): + inputfile = sys.argv[1] + print('Found input file ' + inputfile) + else: + raise Exception('Command line arg given but input file does not exist:' + ' {}'.format(sys.argv[1])) + else: + raise Exception('An input file is required as argument!') + + + start_time = time.time() + + + options = inout.read_parameters(inputfile) + ROUTINE(options) + end_time = time.time() + CLOCK(start_time,end_time) + + + +# END + + + + + + + diff --git a/codes/MATLAB/createU.m b/codes/MATLAB/createU.m new file mode 100644 index 0000000..67eb34e --- /dev/null +++ b/codes/MATLAB/createU.m @@ -0,0 +1,57 @@ +clear all; close all + +folder_name = uigetdir([],'Load Folder...'); + +data = load(strcat(folder_name,'/data.mat')); +SEG = load(strcat(folder_name,'/SEG.mat')); + +data = data.data; +SEG = SEG.SEG; + + +VENC = data.VENC; +VoxelSize = data.voxel_MR; + +vel_AP = data.MR_PCA_AP; +vel_RL = data.MR_PCA_RL; +vel_FH = data.MR_PCA_FH; + +SEG2 = permute(SEG,[2,3,1]); +SEG2 = SEG2(:,:,:); + + +vel_AP_seg = vel_AP.*SEG2(2:end-1,2:end-1,2:end-1); +vel_RL_seg = vel_RL.*SEG2(2:end-1,2:end-1,2:end-1); +vel_FH_seg = vel_FH.*SEG2(2:end-1,2:end-1,2:end-1); + + + + +u_R1 = [] ; +u_R1.x = vel_FH_seg; +u_R1.y = vel_AP_seg; +u_R1.z = vel_RL_seg; +u_R1.VoxelSize = VoxelSize; +save('/home/yeye/Desktop/u_R1.mat','u_R1'); +disp('data saved') +%% +%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% FIGURES +%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +figure +size_vel = size(vel_FH); +for n=1:size_vel(3) + imshow(squeeze(vel_FH_seg(:,:,n,8)),[-100,100],'InitialMagnification',300); + colormap(gca); + pause(0.1) +end +%% +size_seg2 = size(SEG2); +for n=1:size_seg2(3) + imshow(squeeze(SEG2(:,:,n)),'InitialMagnification',300); + colormap(gca); + pause(0.1) +end + + diff --git a/codes/MATLAB/leo/CREATE_MESH.m b/codes/MATLAB/leo/CREATE_MESH.m new file mode 100755 index 0000000..47bab09 --- /dev/null +++ b/codes/MATLAB/leo/CREATE_MESH.m @@ -0,0 +1,14 @@ +% Program to create a structured mesh using the codes of Leo Sok +clear all; close all + +nodes = load('LEO_files/nodes.txt'); +ux = load('LEO_files/ux.txt') ; +uy = load('LEO_files/uy.txt') ; +uz = load('LEO_files/uz.txt') ; +u = sqrt(ux.^2 + uy.^2 + uz.^2); +resol = load('LEO_files/resol.txt') ; +dx = resol(1); dy = resol(2) ; dz = resol(3); + +nodes_masked = maskFEM(nodes,u); +[N,tets,faces] = meshStructTess(nodes_masked,dx,dy,dz,0,0); +writemesh('/home/yeye/Desktop/leomesh',N,tets,faces) \ No newline at end of file diff --git a/codes/MATLAB/leo/maskFEM.m b/codes/MATLAB/leo/maskFEM.m new file mode 100755 index 0000000..b7dca59 --- /dev/null +++ b/codes/MATLAB/leo/maskFEM.m @@ -0,0 +1,19 @@ +function nodes2 = maskFEM(nodes,vel) + +a = []; +b = []; +c = []; +ind = 1; + +for i=1:length(nodes) +if vel(i)>0 + a(ind) = nodes(i,1); + b(ind) = nodes(i,2); + c(ind) = nodes(i,3); + ind = ind +1; +end +end + +nodes2 = [a', b', c']; + + diff --git a/codes/MATLAB/leo/meshStructTess.m b/codes/MATLAB/leo/meshStructTess.m new file mode 100755 index 0000000..4e23f07 --- /dev/null +++ b/codes/MATLAB/leo/meshStructTess.m @@ -0,0 +1,169 @@ +function [nodes, tets, faces, P] = meshStructTess(nodes, dx, dy, dz, check_mesh, plot_mesh) +%% [nodes, tets, faces] = meshStructTess(nodes, dx, dy, dz, check_mesh, plot_mesh) +% Generate a tessalation from a list of structured nodes. +% input: nodes: n times 3 matrix with on the rows the coordinates of +% the n points in the mesh +% dx, dy, dz: the mesh-size in the directions x, y and z +% check_mesh: if true, then it solves a Poisson problem +% plot_mesh: if true, then it plots the mesh +% output: nodes: m times 3 matrix with on the rows the coordinates of +% the m <= n points in the triangulationedi +% tets: l times 4 matrix with on the rows the tetrahedra +% faces: k times 3 matrix with on the rows the triangles of the +% boundary of the mesh +% P: Transformation matrix from input nodes to output nodes. +% Useful also for transforming node-valued functions on +% the input nodes to node-valued functions on the output +% nodes +% +% The triangulation can be plotted using tetramesh(tets,nodes) + + +% compute the minimum and number of points in each direction +if size(nodes,1) < 4 + error('Triangulation needs at least 4 points') +end +mn = min(nodes); +xmin = mn(1); +ymin = mn(2); +zmin = mn(3); + +mn = max(nodes); +xmax = mn(1); +ymax = mn(2); +zmax = mn(3); + +nx = round((xmax-xmin)/dx +1); +ny = round((ymax-ymin)/dy +1); +nz = round((zmax-zmin)/dz +1); + +Nnodes = size(nodes,1); + + +% Define tensor which consist of nodes indices, used for the creation of +% the tetrahedra + +nodes3d = zeros(nx,ny,nz); % preallocate +for i=1:Nnodes + nodes3d(round((nodes(i,1)-xmin)/dx)+1,round((nodes(i,2)-ymin)/dy)+1,round((nodes(i,3)-zmin)/dz)+1)=i; +end + + +disp('Creating Tetrahedra') + +% create tetrahedral mesh in cube, which we will reuse. +ii = 1; +X = zeros(8,3); +for i=0:1 + for j=0:1 + for k=0:1 + X(ii,:) = [i,j,k]; + ii = ii+1; + end + end +end +cubetet = delaunay(X); + +% Run through the mesh +el = 1; +Tetrahedra = zeros(6*(nnz(nodes3d)),4); % preallocate + +for i=1:nx-1 + for j=1:ny-1 + for k=1:nz-1 + % take [i:i+1,j:j+1,k:k+1] as cube + nod = zeros(1,8); % perallocate + + for l = 1:8 + % nod is vector with node indices of cube + nod(l) = nodes3d(i + X(l,1), j + X(l,2), k + X(l,3)); + end + + if nnz(nod) == 8 % then the cube is inside the mesh + tet = nod(cubetet); + else % then there is at least one point of the cube outside the mesh + Xs = X(logical(nod),:); % take only nodes inside the mesh + nodx = nod(logical(nod)); + if nnz(nod) == 4 % 4 nodes, check if points are coplanar + C = cross(Xs(2,:)-Xs(1,:), Xs(3,:)-Xs(1,:)); + cop = logical(dot(C,Xs(4,:)-Xs(1,:))); + % if cop = 0, then points are coplanar end thus no + % tetrahedra exists. + end + if (nnz(nod)>4) || (nnz(nod) == 4 && cop) + % create tetrahedra + tet1 = delaunay(Xs); + tet = nodx(tet1); + else % no tetrahedra exists + tet = []; + end + end + + % add new tetrahedra to list + Tetrahedra(el:el+size(tet,1)-1,:) = tet; + el = el+size(tet,1); + end + end +end + +tets = Tetrahedra(1:el-1,:); % Delete extra preallocated rows. +clear Tetrahedra + +disp([num2str(size(tets,1)), ' tetrahedra created']) + +% Delete nodes which are not in any tetrahedra. +disp('Update mesh') +contr = zeros(size(nodes,1),1); +for i=1:size(tets,1) + for j=1:4 + contr(tets(i,j))=1; + end +end + +nodes = nodes(logical(contr),:); + +% compute P +P = speye(Nnodes); +P = P(logical(contr),:); + +disp([num2str(nnz(~contr)), ' unused nodes in triangulation deleted.']) + +disp('Update tetrahedra') + +% make tetrahedra compatible with new node indices +cumcon = cumsum(~contr)'; +tets = tets - cumcon(tets); + +% create triangles +if size(tets,1) == 0 + warning('No tetrahedra created') + faces = zeros(0,3); +else + disp('Create Triangles') + faces = freeBoundary(triangulation(tets,nodes)); + disp([num2str(size(faces,1)), ' triangles created']) +end + +% checking the mesh by solving a Poisson problem +if check_mesh + % Builds the P1 stiffness matrix from tets and nodes + [A,volumes]=stifness_matrixP1_3D(tets,nodes); + % Check if element volumes may be negative + if any(volumes<=0) + warning('Some elements have zero or negative volume') + end + % solve the Poisson problem with Dirichlet BC + A(2:end,2:end)\ones(size(A(2:end,2:end),1),1); + disp('If there are no warnings, it probably means that the mesh is fine') +end + +% Plots mesh +if plot_mesh + tetramesh(tets,nodes) + xlabel('x') + ylabel('y') + zlabel('z') +end + +end + diff --git a/codes/MATLAB/leo/writemesh.m b/codes/MATLAB/leo/writemesh.m new file mode 100755 index 0000000..a79ad0a --- /dev/null +++ b/codes/MATLAB/leo/writemesh.m @@ -0,0 +1,97 @@ +function writemesh(varargin) +%% writemesh(path, mesh) +% Save triangulation as path.xml and path.msh +% mesh is a struct with fields Pts, Tet, Tri +% alernatively one can use writemesh(path, Pts, Tet, Tri) +% Pts should by a n times 3 matrix consisting points of the mesh +% Tet is the m times 4 matrix consisting the tetrahedra +% Tri is the l times 3 matrix consisting the triangles at the boundary + +if nargin > 3 + mesh.Pts=varargin{2}; + mesh.Tet=varargin{3}; + mesh.Tri=varargin{4}; + writemesh(varargin{1},mesh,varargin(nargin)); + +elseif isstruct(varargin{2}) + rootMeshFile = varargin{1}; + + % NEW FILE + obj = [rootMeshFile,'.msh']; + meshfile = fopen(obj,'w'); + + obj2 = [rootMeshFile,'.xml']; + xmlfile = fopen(obj2,'w'); + + % MESH + fprintf(meshfile,['$MeshFormat','\n']); + fprintf(meshfile,['2.2 0 8','\n']); + fprintf(meshfile,['$EndMeshFormat','\n']); + + fprintf(xmlfile,['','\n']); + fprintf(xmlfile,'\n'); + fprintf(xmlfile,['','\n']); + + mesh = varargin{2}; + + Nodes = mesh.('Pts'); + mesh = rmfield(mesh,'Pts'); + + Nodes = [(1:size(Nodes,1))' Nodes(:,1:3)]; + + % POINTS + if ~strcmp(varargin{nargin},'mute') + disp('Write Points') + end + fprintf(meshfile,['$Nodes','\n']); + fprintf(meshfile,['%i','\n'],size(Nodes,1)); + fprintf(xmlfile,[' ','\n']); + fprintf(xmlfile,[' ','\n'],size(Nodes,1)); + + + fprintf(meshfile,'%i %13.6f %13.6f %13.6f\n',Nodes'); + + Nodes(:,1) = Nodes(:,1) - 1; + + fprintf(xmlfile,' \n',Nodes'); + + fprintf(meshfile,['$EndNodes','\n']); + fprintf(meshfile,['$Elements','\n']); + fprintf(meshfile,['%i','\n'],size(mesh.Tet,1)+size(mesh.Tri,1)); + fprintf(xmlfile,[' ','\n']); + fprintf(xmlfile,[' ','\n'],size(mesh.Tet,1)); + + % Triangles + + if ~strcmp(varargin{nargin},'mute') + disp('Write Triangles') + end + + tri = mesh.('Tri'); + tri = [(1:size(tri,1))' 2*ones(size(tri,1),1) 2*ones(size(tri,1),1) zeros(size(tri,1),1) 2*ones(size(tri,1),1) tri(:,1:3)]; + fprintf(meshfile,'%i %i %i %i %i %i %i %i\n',tri'); + + + + % Tetrahedra + if ~strcmp(varargin{nargin},'mute') + disp('Write Tetrahedra') + end + + tet = mesh.('Tet'); + tet = [(size(tri,1)+1:size(tri,1)+size(tet,1))' 4*ones(size(tet,1),1) 2*ones(size(tet,1),1) zeros(size(tet,1),1) ones(size(tet,1),1) tet(:,1:4)]; + fprintf(meshfile,'%i %i %i %i %i %i %i %i %i\n',tet'); + + tet = mesh.('Tet'); + tet = [(0:size(tet,1)-1)' (tet(:,1:4)-1)]; + fprintf(xmlfile,' \n',tet'); + + + + fprintf(meshfile,['$EndElements','\n']); + fprintf(xmlfile,' \n \n\n'); + + fclose('all'); +end + + diff --git a/codes/MATLAB/load_dicom.m b/codes/MATLAB/load_dicom.m new file mode 100644 index 0000000..35eb488 --- /dev/null +++ b/codes/MATLAB/load_dicom.m @@ -0,0 +1,126 @@ +clear all ; close all +% Load dicom + + +name = 'Ronald' ; + +if strcmp(name, 'Ronald') + path_all = [ + '/home/yeye/Desktop/PhD/MEDICAL_DATA/DatosSEPT2019/20190909_Ronald/FH/DICOM/IM_0001', + '/home/yeye/Desktop/PhD/MEDICAL_DATA/DatosSEPT2019/20190909_Ronald/AP/DICOM/IM_0001', + '/home/yeye/Desktop/PhD/MEDICAL_DATA/DatosSEPT2019/20190909_Ronald/RL/DICOM/IM_0001' + ] ; +end + +if strcmp(name, 'Jeremias') + path_all = [ + '/home/yeye/Desktop/PhD/MEDICAL_DATA/DatosSEPT2019/20190909_Jeremias/FH/DICOM/IM_0001', + '/home/yeye/Desktop/PhD/MEDICAL_DATA/DatosSEPT2019/20190909_Jeremias/AP/DICOM/IM_0001', + '/home/yeye/Desktop/PhD/MEDICAL_DATA/DatosSEPT2019/20190909_Jeremias/RL/DICOM/IM_0001' + ] ; +end + +if strcmp(name, 'Hugo') + path_all = [ + '/home/yeye/Desktop/PhD/MEDICAL_DATA/DatosSEPT2019/20190924_Hugo/Dicom/DICOM/IM_0013', + '/home/yeye/Desktop/PhD/MEDICAL_DATA/DatosSEPT2019/20190924_Hugo/Dicom/DICOM/IM_0009', + '/home/yeye/Desktop/PhD/MEDICAL_DATA/DatosSEPT2019/20190924_Hugo/Dicom/DICOM/IM_0005' + ] ; +end + +for i=1:3 + + if i==1 + %path = '/home/yeye/Desktop/PhD/MEDICAL_DATA/DatosSEPT2019/20190924_Paloma/Dicom/DICOM/IM_0013' + disp('Reading the FH component from ...') + path = path_all(1,:) + end + + if i==2 + %path = '/home/yeye/Desktop/PhD/MEDICAL_DATA/DatosSEPT2019/20190924_Paloma/Dicom/DICOM/IM_0009' ; + disp('Reading the AP component from ...') + path = path_all(2,:) + end + + if i==3 + %path = '/home/yeye/Desktop/PhD/MEDICAL_DATA/DatosSEPT2019/20190924_Paloma/Dicom/DICOM/IM_0005' ; + disp('Reading the RL component from ...') + path = path_all(3,:) + end + + +I_info = dicominfo(path); +I = double(dicomread(path)); +VENC = eval(['I_info.PerFrameFunctionalGroupsSequence.Item_1.MRVelocityEncodingSequence.Item_1.VelocityEncodingMaximumValue']) ; +heart_rate = eval(['I_info.PerFrameFunctionalGroupsSequence.Item_1.Private_2005_140f.Item_1.HeartRate']); + + +MAG = zeros(size(I,1),size(I,2),I_info.Private_2001_1018,I_info.Private_2001_1017); +PHASE = zeros(size(I,1),size(I,2),I_info.Private_2001_1018,I_info.Private_2001_1017); + +for n=1:size(I,4) + + RI = eval(['I_info.PerFrameFunctionalGroupsSequence.Item_',num2str(n),'.Private_2005_140f.Item_1.RescaleIntercept']); % intercept + RS = eval(['I_info.PerFrameFunctionalGroupsSequence.Item_',num2str(n),'.Private_2005_140f.Item_1.RescaleSlope']); % slope + cp = eval(['I_info.PerFrameFunctionalGroupsSequence.Item_',num2str(n),'.Private_2005_140f.Item_1.Private_2001_1008']); %cp + slc = eval(['I_info.PerFrameFunctionalGroupsSequence.Item_',num2str(n),'.Private_2005_140f.Item_1.Private_2001_100a']); %scl + id = eval(['I_info.PerFrameFunctionalGroupsSequence.Item_',num2str(n),'.Private_2005_140f.Item_1.Private_2005_106e']); % PCA o FFE + + if strcmp(id,'FFE')==1 + MAG(:,:,slc,cp) = I(:,:,1,n)*RS + RI; + else + PHASE(:,:,slc,cp) = I(:,:,1,n)*RS + RI; + end + +end + + +MASK = double(abs((PHASE==PHASE(1,1,1,1))-1)); +PHASE = PHASE.*MASK; + + +if i==1 + MR_FFE_FH = MAG; + MR_PCA_FH = VENC*PHASE/pi/100; +end + +if i==2 + MR_FFE_AP = MAG; + MR_PCA_AP = VENC*PHASE/pi/100; +end +if i==3 + MR_FFE_RL = MAG; + MR_PCA_RL = VENC*PHASE/pi/100; +end + + +end + + +disp('Saving the data ...') + +spaceslices = eval(['I_info.PerFrameFunctionalGroupsSequence.Item_1.PixelMeasuresSequence.Item_1.SpacingBetweenSlices']); +pixelspacing = eval(['I_info.PerFrameFunctionalGroupsSequence.Item_1.PixelMeasuresSequence.Item_1.PixelSpacing']); + +disp('voxel-size recognized:') +voxel_MR = [pixelspacing(1),pixelspacing(1),spaceslices] + + +data = []; +data.MR_FFE_AP = MR_FFE_AP; +data.MR_FFE_RL = MR_FFE_RL; +data.MR_FFE_FH = MR_FFE_FH; +data.MR_PCA_AP = MR_PCA_AP; +data.MR_PCA_RL = MR_PCA_RL; +data.MR_PCA_FH = MR_PCA_FH; +data.type = 'DAT'; +data.VENC = VENC ; +data.voxel_MR = voxel_MR; +data.heart_rate = heart_rate; + +save('/home/yeye/Desktop/data.mat','data','-v7.3'); +disp('data saved') + + + + \ No newline at end of file diff --git a/codes/MRI.py b/codes/MRI.py new file mode 100644 index 0000000..8ebba11 --- /dev/null +++ b/codes/MRI.py @@ -0,0 +1,1936 @@ +################################################################ +# +# Workspace for MRI analysis of the 4Dflow data +# +# written by Jeremias Garay L: j.e.garay.labra@rug.nl +# Fernanda te amo +# for autoreload in ipython3 +# %load_ext autoreload +# %autoreload 2 +################################################################ +import h5py +from dPdirectestim.dPdirectestim import * +from dolfin import * +import dolfin +import numpy as np +import sys, os +from mpi4py import MPI +from common import inout +import time + +if '2017' in dolfin.__version__: + #class MPI(MPI): + # comm_world = mpi_comm_world() + set_log_active(False) +else: + PRINT_BARS = False + parameters["std_out_all_processes"] = False + +def Etcetera(mode): + if mode=='happy': + print(r""" + /\ /\ + //\\_//\\ ____ + \_ _/ / / + / ^ ^ \ /^^^] + \_\O/_/ [ ] + / \_ [ / + \ \_ / / + [ [ / \/ _/ + _[ [ \ /_/ + """) + + if mode=='serious': + print(r""" + |\__/| + / \ + /_.- -,_\ + \@/ + """) + +def dealiased(VENC,vx,vy,vz): + + vx2 = np.zeros(vx.shape) + vy2 = np.zeros(vy.shape) + vz2 = np.zeros(vz.shape) + + badx_pos = np.where(vx>VENC) + badx_neg = np.where(vx<-VENC) + bady_pos = np.where(vy>VENC) + bady_neg = np.where(vy<-VENC) + badz_pos = np.where(vz>VENC) + badz_neg = np.where(vz<-VENC) + # More than VENC + vx2[badx_pos] = -(2*VENC - vx[badx_pos]) + vy2[bady_pos] = -(2*VENC - vy[bady_pos]) + vz2[badz_pos] = -(2*VENC - vz[badz_pos]) + # Less than VENC + vx2[badx_neg] = 2*VENC + vx[badx_neg] + vy2[bady_neg] = 2*VENC + vy[bady_neg] + vz2[badz_neg] = 2*VENC + vz[badz_neg] + # The rest + otherx = np.where(vx2==0) + othery = np.where(vy2==0) + otherz = np.where(vz2==0) + vx2[otherx] = vx[otherx] + vy2[othery] = vy[othery] + vz2[otherz] = vz[otherz] + + return [vx2,vy2,vz2] + +def checkpoint_norm(MESH,fieldpath,mode): + V = MESH['FEM'] + v = Function(V) + path = fieldpath + 'checkpoint/' + # Checkpoints folders + unsort_indexes = os.listdir(path) + indexes = [int(x) for x in unsort_indexes] + indexes.sort() + norm = np.zeros([len(indexes)]) + j = 0 + comm = MPI.COMM_WORLD + + if mode=='ct': + # CT DATA + for l in indexes: + path1 = path + str(l) + '/u.h5' + hdf = HDF5File(MESH['mesh'].mpi_comm(),path1,'r') + hdf.read(v, 'u/vector_0') + hdf.close() + norm[j] = np.linalg.norm(v.vector().get_local()) + j = j+1 + + if mode=='measurement': + # MEASUREMENT + path2 = fieldpath + 'measurements/' + j = 0 + for l in indexes: + meapath = path2 + 'u' + str(l) + '.h5' + comm = MPI.COMM_WORLD + hdf = HDF5File(MESH['mesh'].mpi_comm(),meapath,'r') + hdf.read(v, 'u/vector_0') + hdf.close() + norm[j] = np.linalg.norm(v.vector().get_local()) + j = j+1 + + + if mode=='roukf': + indexes2 = indexes[1:-1] + j = 1 + for l in indexes2: + path3 = fieldpath + 'roukf/checkpoint/' + str(l) + '/X0.h5' + hdf = HDF5File(MESH['mesh'].mpi_comm(),path3,'r') + hdf.read(v, 'X') + hdf.close() + norm[j] = np.linalg.norm(v.vector().get_local()) + j = j+1 + + + return norm + +def LOADmesh(meshtype,resol=None,boxsize=None,meshpath=None, ranges=None): + + if meshtype=='box_zeros': + # The size of the mesh is given + # The spacements are given + # The x range goes from 0 + [Lx, Ly, Lz] = boxsize + [ddx, ddy, ddz] = resol + x0 = 0 + y0 = 0 + z0 = 0 + x1 = (Lx-1)*ddx + y1 = (Ly-1)*ddy + z1 = (Lz-1)*ddz + mesh0 = BoxMesh(Point(x0, y0, z0), Point(x1, y1, z1), Lx-1, Ly-1, Lz-1) + P1 = FunctionSpace(mesh0, "Lagrange", 1) + # This need to be saved from Leo's construction + Xt = P1.tabulate_dof_coordinates() + #boundaries = MeshFunction('size_t', mesh0 , mesh0.topology().dim() - 1) + #XDMFFile(path2).write(boundaries) + if '2017' in dolfin.__version__: + Xt = np.reshape(Xt, (round(Xt.size/3), 3)) + SqXt = np.zeros(Xt.shape) + for k in range(Xt.shape[0]): + xk = round((Xt[k][0]-x0)/ddx) + yk = round((Xt[k][1]-y0)/ddy) + zk = round((Xt[k][2]-z0)/ddz) + SqXt[k, 0] = int(xk) + SqXt[k, 1] = int(yk) + SqXt[k, 2] = int(zk) + if rank == 0: + print('BOX real created: H = ' + str(mesh0.hmin()) + + ' H_max = ' + str(mesh0.hmax())) + + BOX = {} + BOX['mesh'] = mesh0 + BOX['FEM'] = P1 + BOX['nodes'] = Xt + BOX['seq'] = SqXt.astype(int) + BOX['dimension'] = [Lx,Ly,Lz] + return BOX + + if meshtype=='box_ranges': + # The size of the mesh is given + # The X ranges are given + # The spacements are calculated + [Lx,Ly,Lz] = boxsize + x0 = ranges['x'][0] + x1 = ranges['x'][1] + y0 = ranges['y'][0] + y1 = ranges['y'][1] + z0 = ranges['z'][0] + z1 = ranges['z'][1] + ddx = (x1-x0)/(Lx-1) + ddy = (y1-y0)/(Ly-1) + ddz = (z1-z0)/(Lz-1) + mesh0 = BoxMesh(Point(x0, y0, z0), Point(x1, y1, z1), Lx-1, Ly-1, Lz-1) + P1 = FunctionSpace(mesh0, "Lagrange", 1) + Xt = P1.tabulate_dof_coordinates() + if '2017' in dolfin.__version__: + Xt = np.reshape(Xt, (round(Xt.size/3), 3)) + SqXt = np.zeros(Xt.shape) + for k in range(Xt.shape[0]): + xk = round((Xt[k][0]-x0)/ddx) + yk = round((Xt[k][1]-y0)/ddy) + zk = round((Xt[k][2]-z0)/ddz) + SqXt[k, 0] = int(xk) + SqXt[k, 1] = int(yk) + SqXt[k, 2] = int(zk) + if rank == 0: + print('BOX real created: H = ' + str(mesh0.hmin()) + + ' H_max = ' + str(mesh0.hmax())) + + BOX = {} + BOX['mesh'] = mesh0 + BOX['FEM'] = P1 + BOX['nodes'] = Xt + BOX['seq'] = SqXt.astype(int) + BOX['dimension'] = [Lx, Ly, Lz] + return BOX + + if meshtype=='fix_resolution': + # The size of the mesh is given + # The spacements are given + # The X ranges are given + # The X ranges are redefined from the oldest + [Lx,Ly,Lz] = boxsize + [ddx,ddy,ddz] = resol + x0 = ranges['x'][0] + x1 = ranges['x'][1] + y0 = ranges['y'][0] + y1 = ranges['y'][1] + z0 = ranges['z'][0] + z1 = ranges['z'][1] + deltax = (ddx*(Lx-1) - (x1 - x0))/2 + deltay = (ddy*(Ly-1) - (y1 - y0))/2 + deltaz = (ddz*(Lz-1) - (z1 - z0))/2 + x0_new = x0 - deltax + x1_new = x1 + deltax + y0_new = y0 - deltay + y1_new = y1 + deltay + z0_new = z0 - deltaz + z1_new = z1 + deltaz + + mesh0 = BoxMesh(Point(x0_new,y0_new,z0_new),Point(x1_new,y1_new,z1_new),Lx-1,Ly-1,Lz-1) + P1 = FunctionSpace(mesh0, "Lagrange", 1) + Xt = P1.tabulate_dof_coordinates() # This need to be saved from Leo's construction + #boundaries = MeshFunction('size_t', mesh0 , mesh0.topology().dim() - 1) + #XDMFFile('/home/yeye/Desktop/bound.xdmf').write(boundaries) + if '2017' in dolfin.__version__: + Xt = np.reshape(Xt,( round(Xt.size/3) ,3)) + SqXt = np.zeros(Xt.shape) + for k in range(Xt.shape[0]): + xk = round((Xt[k][0]-x0_new)/ddx) + yk = round((Xt[k][1]-y0_new)/ddy) + zk = round((Xt[k][2]-z0_new)/ddz) + SqXt[k, 0] = int(xk) + SqXt[k, 1] = int(yk) + SqXt[k, 2] = int(zk) + + if rank==0: + print('BOX real created: H = ' + str(mesh0.hmin()) + ' H_max = ' + str(mesh0.hmax()) ) + + BOX = {} + BOX['mesh'] = mesh0 + BOX['FEM'] = P1 + BOX['nodes'] = Xt + BOX['seq'] = SqXt.astype(int) + BOX['dimension'] = [Lx, Ly, Lz] + + return BOX + + if meshtype=='cib': + ddx = 2.00032/1000; ddy = 2.00032/1000; ddz = 2.00526316/1000 + x0 = ddx*17 ; y0 = ddy*17; z0 = ddz + Lx = 75; Ly = 85; Lz = 57 + x1 = x0+ddx*(Lx-1); y1 = y0+ddy*(Ly-1); z1 = z0+ddz*(Lz-1) + + + mesh0 = BoxMesh(Point(x0,y0,z0),Point(x1,y1,z1),Lx-1,Ly-1,Lz-1) + P1 = FunctionSpace(mesh0, "Lagrange", 1) + Xt = P1.tabulate_dof_coordinates() + #XDMFFile('mesh_hex.xdmf').write(mesh0) + # MESH HEXA + #mesh0 = BoxMesh.create([Point(x0,y0,z0), Point(x1,y1,z1)], [Lx, Ly, Lz], CellType.Type.hexahedron) + #P1 = FunctionSpace(mesh0, "DG", 0) + #t = P1.tabulate_dof_coordinates() + + if '2017' in dolfin.__version__: + Xt = np.reshape(Xt,( round(Xt.size/3) ,3)) + SqXt = np.zeros(Xt.shape) + + for k in range(Xt.shape[0]): + xk = round((Xt[k][0]-x0)/ddx) + yk = round((Xt[k][1]-y0)/ddy) + zk = round((Xt[k][2]-z0)/ddz) + SqXt[k,0] = int(xk) + SqXt[k,1] = int(yk) + SqXt[k,2] = int(zk) + if rank==0: + print('BOX cib created: H = ' + str(mesh0.hmin()) + ' H_max = ' + str(mesh0.hmax()) ) + + BOX = {} + BOX['mesh'] = mesh0 + BOX['FEM'] = P1 + BOX['nodes'] = Xt + BOX['seq'] = SqXt.astype(int) + BOX['name'] = 'cib' + BOX['dimension'] = [Lx,Ly,Lz] + return BOX + + if meshtype=='cib_RT': + ddx = 1.8/1000; ddy = 1.8/1000; ddz = 1.8/1000 + x0 = ddx*33 ; y0 = ddy*43; z0 = ddz*13 + Lx = 103; Ly = 63; Lz = 47 + x1 = x0+ddx*(Lx-1); y1 = y0+ddy*(Ly-1); z1 = z0+ddz*(Lz-1) + + mesh0 = BoxMesh(Point(x0,y0,z0),Point(x1,y1,z1),Lx-1,Ly-1,Lz-1) + P1 = FunctionSpace(mesh0, "Lagrange", 1) + Xt = P1.tabulate_dof_coordinates() + #XDMFFile('mesh_hex.xdmf').write(mesh0) + # MESH HEXA + #mesh0 = BoxMesh.create([Point(x0,y0,z0), Point(x1,y1,z1)], [Lx, Ly, Lz], CellType.Type.hexahedron) + #P1 = FunctionSpace(mesh0, "DG", 0) + #t = P1.tabulate_dof_coordinates() + + if '2017' in dolfin.__version__: + Xt = np.reshape(Xt,( round(Xt.size/3) ,3)) + SqXt = np.zeros(Xt.shape) + + for k in range(Xt.shape[0]): + xk = round((Xt[k][0]-x0)/ddx) + yk = round((Xt[k][1]-y0)/ddy) + zk = round((Xt[k][2]-z0)/ddz) + SqXt[k,0] = int(xk) + SqXt[k,1] = int(yk) + SqXt[k,2] = int(zk) + if rank==0: + print('BOX cib created: H = ' + str(mesh0.hmin()) + ' H_max = ' + str(mesh0.hmax()) ) + + BOX = {} + BOX['mesh'] = mesh0 + BOX['FEM'] = P1 + BOX['nodes'] = Xt + BOX['seq'] = SqXt.astype(int) + BOX['name'] = 'cib' + BOX['dimension'] = [Lx,Ly,Lz] + return BOX + + if meshtype=='cib_GM': + ddx = 1.8/1000; ddy = 1.8/1000; ddz = 1.8/1000 + x0 = ddx*20 ; y0 = ddy*43; z0 = -ddz*5 + Lx = 110; Ly = 70; Lz = 43 + x1 = x0+ddx*(Lx-1); y1 = y0+ddy*(Ly-1); z1 = z0+ddz*(Lz-1) + + mesh0 = BoxMesh(Point(x0,y0,z0),Point(x1,y1,z1),Lx-1,Ly-1,Lz-1) + P1 = FunctionSpace(mesh0, "Lagrange", 1) + Xt = P1.tabulate_dof_coordinates() + #XDMFFile('mesh_hex.xdmf').write(mesh0) + # MESH HEXA + #mesh0 = BoxMesh.create([Point(x0,y0,z0), Point(x1,y1,z1)], [Lx, Ly, Lz], CellType.Type.hexahedron) + #P1 = FunctionSpace(mesh0, "DG", 0) + #t = P1.tabulate_dof_coordinates() + + if '2017' in dolfin.__version__: + Xt = np.reshape(Xt,( round(Xt.size/3) ,3)) + SqXt = np.zeros(Xt.shape) + + for k in range(Xt.shape[0]): + xk = round((Xt[k][0]-x0)/ddx) + yk = round((Xt[k][1]-y0)/ddy) + zk = round((Xt[k][2]-z0)/ddz) + SqXt[k,0] = int(xk) + SqXt[k,1] = int(yk) + SqXt[k,2] = int(zk) + if rank==0: + print('BOX cib created: H = ' + str(mesh0.hmin()) + ' H_max = ' + str(mesh0.hmax()) ) + + BOX = {} + BOX['mesh'] = mesh0 + BOX['FEM'] = P1 + BOX['nodes'] = Xt + BOX['seq'] = SqXt.astype(int) + BOX['name'] = 'cib' + BOX['dimension'] = [Lx,Ly,Lz] + return BOX + + if meshtype=='aorta': + + if '.xml' in meshpath: + mesh1 = Mesh(meshpath) + Evel1 = VectorElement('Lagrange', mesh1.ufl_cell(), 1) + V1 = FunctionSpace(mesh1, Evel1) + boundaries1 = MeshFunction( + "size_t", mesh1, mesh1.topology().dim()-1) + if '.h5' in meshpath: + mesh1 = Mesh() + hdf1 = HDF5File(mesh1.mpi_comm(), meshpath, 'r') + hdf1.read(mesh1, '/mesh', False) + boundaries1 = MeshFunction( + 'size_t', mesh1, mesh1.topology().dim() - 1) + hdf1.read(boundaries1, '/boundaries') + Evel1 = VectorElement('Lagrange', mesh1.ufl_cell(), 1) + V1 = FunctionSpace(mesh1, Evel1) + + if rank == 0: + print('AORTA created: h_min = ' + str(mesh1.hmin()) + + ' h_max = ' + str(mesh1.hmax())) + + AORTA = {} + AORTA['mesh'] = mesh1 + AORTA['boundaries'] = boundaries1 + AORTA['FEM'] = V1 + AORTA['name'] = 'aorta' + + return AORTA + + if meshtype == 'leo': + + # LEO + mesh = Mesh(meshpath) + Evel = VectorElement('Lagrange', mesh.ufl_cell(), 1) + #Evel = VectorElement('DG',mesh2.ufl_cell(),0) + V = FunctionSpace(mesh, Evel) + boundaries = MeshFunction("size_t", mesh, mesh.topology().dim()-1) + marked = True + + if marked: + class Outlet(SubDomain): + def inside(self, x, on_boundary): + return on_boundary and between(x[2], (11.18, 11.4)) + + class Inlet(SubDomain): + def inside(self, x, on_boundary): + return on_boundary and between(x[2], (7.56, 7.8)) and between(x[0], (10, 16)) + + outlet = Outlet() + inlet = Inlet() + boundaries.set_all(0) + outlet.mark(boundaries, 3) + inlet.mark(boundaries, 2) + + if rank == 0: + print('LEO created: H = ' + str(mesh.hmin()) + + ' H_max = ' + str(mesh.hmax())) + + LEO = {} + LEO['mesh'] = mesh + LEO['FEM'] = V + LEO['boundaries'] = boundaries + + return LEO + + if meshtype=='other': + + if '.xml' in meshpath: + mesh1 = Mesh(meshpath) + Evel1 = VectorElement('Lagrange', mesh1.ufl_cell(), 1) + V1 = FunctionSpace(mesh1, Evel1) + boundaries1 = MeshFunction( + "size_t", mesh1, mesh1.topology().dim()-1) + if '.h5' in meshpath: + mesh1 = Mesh() + hdf1 = HDF5File(mesh1.mpi_comm(), meshpath, 'r') + hdf1.read(mesh1, '/mesh', False) + boundaries1 = MeshFunction( + 'size_t', mesh1, mesh1.topology().dim() - 1) + hdf1.read(boundaries1, '/boundaries') + Evel1 = VectorElement('Lagrange', mesh1.ufl_cell(), 1) + V1 = FunctionSpace(mesh1, Evel1) + + if rank == 0: + print('MESH created: h_min = ' + str(mesh1.hmin()) + + ' h_max = ' + str(mesh1.hmax())) + + MESH = {} + MESH['mesh'] = mesh1 + MESH['boundaries'] = boundaries1 + MESH['FEM'] = V1 + + return MESH + +def CREATEsequences(BOX,AORTA,options): + # Checkpoints folders + checkpoint_path = options['sequence']['checkpoint_path']+'checkpoint/' + unsort_indexes = os.listdir(checkpoint_path) + indexes = [int(x) for x in unsort_indexes] + indexes.sort() + [Lx, Ly, Lz] = BOX['dimension'] + + Lt = len(indexes) + Sqx = np.zeros([Lx, Ly, Lz, Lt]) + Sqy = np.zeros([Lx, Ly, Lz, Lt]) + Sqz = np.zeros([Lx, Ly, Lz, Lt]) + + v1x = Function(BOX['FEM']) + v1y = Function(BOX['FEM']) + v1z = Function(BOX['FEM']) + v2 = Function(AORTA['FEM']) + N_sp = int(options['sequence']['sampling_rate']) + + if rank==0: + print('Total number of checkpoints folders: ',len(indexes)) + + if options['sequence']['sampling_rate']>1: + if rank==0: + print('Applying an undersampling of ' + str(N_sp)) + print('list of indexes',indexes) + + for k in range(0, len(indexes), N_sp): + if rank == 0: + print('READING CHECKPOINT FOLDER: ' + str(indexes[k])) + + hdf = HDF5File(AORTA['mesh'].mpi_comm( + ), checkpoint_path + str(indexes[k])+'/u.h5', 'r') + hdf.read(v2, 'u/vector_0') + hdf.close() + + LagrangeInterpolator.interpolate(v1x, v2.sub(0)) + LagrangeInterpolator.interpolate(v1y, v2.sub(1)) + LagrangeInterpolator.interpolate(v1z, v2.sub(2)) + + v1_gather = v1x.vector().gather( + np.array(range(BOX['FEM'].dim()), 'intc')) + v2_gather = v1y.vector().gather( + np.array(range(BOX['FEM'].dim()), 'intc')) + v3_gather = v1z.vector().gather( + np.array(range(BOX['FEM'].dim()), 'intc')) + + SqXt = BOX['seq'] + #SqXt = SqXt.astype(int) + # To Gather the Sorting-Sequence in parallel with Gatherv + loc_X = SqXt[:, 0] + loc_Y = SqXt[:, 1] + loc_Z = SqXt[:, 2] + sendbuf_X = np.array(loc_X) + sendbuf_Y = np.array(loc_Y) + sendbuf_Z = np.array(loc_Z) + sendcounts_X = np.array(comm.gather(len(sendbuf_X), 0)) + sendcounts_Y = np.array(comm.gather(len(sendbuf_Y), 0)) + sendcounts_Z = np.array(comm.gather(len(sendbuf_Z), 0)) + + if rank == 0: + SStot_X = np.zeros([Lx*Ly*Lz], dtype=int) + SStot_Y = np.zeros([Lx*Ly*Lz], dtype=int) + SStot_Z = np.zeros([Lx*Ly*Lz], dtype=int) + else: + SStot_X = None + SStot_Y = None + SStot_Z = None + + comm.Gatherv(sendbuf=sendbuf_X, recvbuf=( + SStot_X, sendcounts_X), root=0) + comm.Gatherv(sendbuf=sendbuf_Y, recvbuf=( + SStot_Y, sendcounts_Y), root=0) + comm.Gatherv(sendbuf=sendbuf_Z, recvbuf=( + SStot_Z, sendcounts_Z), root=0) + + if rank == 0: + for l in range(Lx*Ly*Lz): + Sqx[SStot_X[l], SStot_Y[l], SStot_Z[l], k] = v1_gather[l] + Sqy[SStot_X[l], SStot_Y[l], SStot_Z[l], k] = v2_gather[l] + Sqz[SStot_X[l], SStot_Y[l], SStot_Z[l], k] = v3_gather[l] + + if options['sequence']['sampling_rate']>1: + Sqx = Sqx[:, :, :, 0::N_sp] + Sqy = Sqy[:, :, :, 0::N_sp] + Sqz = Sqz[:, :, :, 0::N_sp] + + if rank == 0: + print('saving the sequences' + options['sequence']['checkpoint_path']) + savepath = options['sequence']['checkpoint_path'] + options['sequence']['name'] + '.npz' + np.savez_compressed(savepath, x=Sqx, y=Sqy, z=Sqz) + + + return [Sqx,Sqy,Sqz] + +def LOADsequences(loadpath): + # for loading existing sequences alocated in loadpath + if rank==0: + print('{reading} ' + loadpath) + + if '.mat' in loadpath: + import scipy.io as sio + S = sio.loadmat(loadpath) + S = S['u_R1'] + Sqx = S['x'][0][0] + Sqy = S['y'][0][0] + Sqz = S['z'][0][0] + else: + S = np.load(loadpath) + Sqx = S['x'] + Sqy = S['y'] + Sqz = S['z'] + + return [Sqx,Sqy,Sqz] + +def SqtoH5(BOX,MESH,Sqx,Sqy,Sqz): + + Xt = BOX['nodes'] + SqXt = BOX['seq'] + P1 = BOX['FEM'] + V = MESH['FEM'] + velocity = {} + Lt = Sqx.shape[3] + VX = V.sub(0).collapse() + VY = V.sub(1).collapse() + VZ = V.sub(2).collapse() + vv_x = Function(VX) + vv_y = Function(VY) + vv_z = Function(VZ) + + if rank == 0: + print('{SQtoH5} total number of timesteps: ' + str(Lt)) + + nit = 0 + nit_tot = (Lt-1)/20 + + for t in range(Lt): + if rank == 0: + if PRINT_BARS: + if np.mod(t, nit_tot) < 1: + sys.stdout.write('\r') + # Progress bar + sys.stdout.write( + "{SQtoH5} [%-40s] %d%%" % ('=='*nit, 100*t/Lt)) + sys.stdout.flush() + nit = nit + 1 + else: + print('iteration number:', t) + + v1_x = Function(P1) + v1_y = Function(P1) + v1_z = Function(P1) + + values_x = np.zeros(v1_x.vector().get_local().shape) + values_y = np.zeros(v1_y.vector().get_local().shape) + values_z = np.zeros(v1_z.vector().get_local().shape) + S0x = Sqx[:, :, :, t] + S0y = Sqy[:, :, :, t] + S0z = Sqz[:, :, :, t] + + for k in range(Xt.shape[0]): + values_x[k] = S0x[SqXt[k, 0], SqXt[k, 1], SqXt[k, 2]] + values_y[k] = S0y[SqXt[k, 0], SqXt[k, 1], SqXt[k, 2]] + values_z[k] = S0z[SqXt[k, 0], SqXt[k, 1], SqXt[k, 2]] + + v1_x.vector()[:] = values_x + v1_y.vector()[:] = values_y + v1_z.vector()[:] = values_z + + LagrangeInterpolator.interpolate(vv_x, v1_x) + LagrangeInterpolator.interpolate(vv_y, v1_y) + LagrangeInterpolator.interpolate(vv_z, v1_z) + + v = Function(V) + assign(v.sub(0), vv_x) + assign(v.sub(1), vv_y) + assign(v.sub(2), vv_z) + + velocity[t] = v + + + return velocity + +def MASKED(S_REF,S_RAW): + + [Sq0x,Sq0y,Sq0z] = S_REF + [Sq1x,Sq1y,Sq1z] = S_RAW + + if Sq0z.shape != Sq1z.shape: + print('Original',Sq0z.shape) + print('To mask',Sq1z.shape) + + raise Exception('Dimension of masking sequences not match!') + + # masked Sq1 according to Sq0. Both sequences must have the same sizes. + Sq2x = np.zeros(Sq0x.shape) + Sq2y = np.zeros(Sq0y.shape) + Sq2z = np.zeros(Sq0z.shape) + + nonzerox = np.where(Sq0x!=0) + nonzeroy = np.where(Sq0y!=0) + nonzeroz = np.where(Sq0z!=0) + + Sq2x[nonzerox] = Sq1x[nonzerox] + Sq2y[nonzeroy] = Sq1y[nonzeroy] + Sq2z[nonzeroz] = Sq1z[nonzeroz] + + return [Sq2x,Sq2y,Sq2z] + +def READcheckpoint(MESH,mode,ckpath,under_rate,name,zeros=True): + + V = MESH['FEM'] + W = MESH['FEM'].sub(0).collapse() + # Checkpoints folders + unsort_indexes = os.listdir(ckpath) + indexes = [int(x) for x in unsort_indexes] + indexes.sort() + + numt = 0 + nit = 0 + nit_tot = (len(indexes)-1)/20 + + from dolfin import HDF5File + if mode == 'u': + velocity = {} + for k in range(0, len(indexes), under_rate): + path = ckpath + str(indexes[k]) + '/'+name+'.h5' + + if zeros: + if indexes[k] < 10 and indexes[k] > 0: + path = ckpath + '0' + str(indexes[k]) + '/'+name+'.h5' + + if rank == 0: + if PRINT_BARS: + if np.mod(numt, nit_tot) < 1: + sys.stdout.write('\r') + sys.stdout.write( + "{vel checkpoint} [%-40s] %d%%" % ('=='*nit, 100*numt/(len(indexes)-1))) + sys.stdout.flush() + nit = nit + 1 + + #if options['P_measurement']=='p2': + #v = Function(V) + #vmix = Function(V) + #v,p = vmix.split() + #from dolfin import HDF5File + #hdf = HDF5File(AORTA['mesh'].mpi_comm(), path, 'r') + #hdf.read(v, 'u') + #hdf.close() + #udat = h5py.File(path, 'r') + #v.vector()[:] = udat['u']['vector_0'] + #else: + + v = Function(V) + comm = MPI.COMM_WORLD + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(v, 'u/vector_0') + hdf.close() + velocity[numt] = v + numt = numt + 1 + + return velocity + + if mode == 'p': + pressure = {} + for k in range(0, len(indexes), under_rate): + path = ckpath + str(indexes[k]) + '/'+name+'.h5' + if zeros: + if indexes[k] < 10 and indexes[k] > 0: + path = ckpath + '0' + str(indexes[k]) + '/'+name+'.h5' + + if rank == 0: + if PRINT_BARS: + if np.mod(numt, nit_tot) < 1: + sys.stdout.write('\r') + sys.stdout.write( + "{press checkpoint} [%-40s] %d%%" % ('=='*nit, 100*numt/(len(indexes)-1))) + sys.stdout.flush() + nit = nit + 1 + p = Function(W) + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(p, 'p/vector_0') + hdf.close() + pressure[numt] = p + numt = numt + 1 + + return pressure + +def CHANGEmesh(MESH,field,mode): + # To change between meshes the same result + field2 = {} + if mode=='velocity': + V = MESH['FEM'] + elif mode=='pressure': + V = MESH['FEM'].sub(0).collapse() + else: + raise Exception('You need to assign a mode for the changing!') + for k in range(len(list(field))): + if rank==0: + print('CHANGING MESH: index',k) + v2 = Function(V) + LagrangeInterpolator.interpolate(v2,field[k]) + field2[k] = v2 + + + return field2 + +def GradP(MESH,pressure,options): + + W = MESH['FEM'].sub(0).collapse() + boundaries = MESH['boundaries'] + barye2mmHg = 1/1333.22387415 + + Tf = Constant(options['Tf']) + dt = Constant(options['Tf']/len(list(pressure))) + NT = int(float(Tf)/float(dt)) + + ind = 0 + t = float(dt) + ds = Measure("ds", subdomain_data=boundaries) + ones = interpolate(Constant(1),W) + DELTA_p = np.zeros([NT]) + + p0 = Function(W) + nit = 0 + nit_tot = (NT-1)/20 + + zero_point = None + if options['reference']['fix_const']: + zero_point = options['reference']['zero_point'] + zero_point = np.array(zero_point) + ndim = W.mesh().topology().dim() + zero_point = W.tabulate_dof_coordinates().reshape((-1, ndim))[0] + + #################### THE TIME LOOP ######################### + while ind < NT: + p0.assign(pressure[ind]) + + if rank == 0: + if PRINT_BARS: + if np.mod(ind, nit_tot) < 1: + sys.stdout.write('\r') + # Progress bar + sys.stdout.write("{ref} [%-40s] %f seg" % + ('=='*nit, round(t, 2))) + sys.stdout.flush() + nit = nit + 1 + + if options['reference']['fix_const']: + p0.vector()[:] -= p0(zero_point) + + i_pin = assemble(p0*ds(2)) + i_pout = assemble(p0*ds(3)) + i_s2 = assemble(ones*ds(2)) + i_s3 = assemble(ones*ds(3)) + + DELTA_p[ind] = barye2mmHg*(i_pin/i_s2-i_pout/i_s3) + ind = ind + 1 + t = t + float(dt) + + if options['reference']['save']: + + if rank==0: + np.savetxt(options['reference']['savepath'],DELTA_p) + print('\n Pressure drop save in ' + options['reference']['savepath']) + +def Fluxes(MESH,velocity,options,bnd): + + mesh = MESH['mesh'] + W = MESH['FEM'] + boundaries = MESH['boundaries'] + n = FacetNormal(mesh) + Tf = Constant(options['Tf']) + rho = Constant(options['density']) + dt = Constant(options['Tf']/len(list(velocity))) + NT = int(float(Tf)/float(dt)) + ind = 0 + t = float(dt) + ds = Measure("ds", subdomain_data=boundaries) + QQ = {} + for k in bnd: + QQ[k] = np.zeros([NT]) + + u = Function(W) + nit = 0 + nit_tot = (NT-1)/20 + #################### THE TIME LOOP ######################### + while indVENC) + INDy = np.any(np.abs(vy)>VENC) + INDz = np.any(np.abs(vz)>VENC) + + if INDx or INDy or INDz: + if not options['phase_contrast']['dealiased']: + if rank==0: + raise Exception('There is some velocity greater or lower than VENC. You should turn dealised true!') + + + if options['phase_contrast']['dealiased']: + [vx_d,vy_d,vz_d] = dealiased(VENC,vx,vy,vz) + else: + vx_d = vx; vy_d = vy; vz_d = vz + + if rank==0: + print('saving velocity as ' + options['phase_contrast']['output']) + np.savez_compressed(options['phase_contrast']['output'], x=vx_d, y=vy_d, z=vz_d) + + if 'resize' in options: + if options['resize']['apply']: + if rank == 0: + print('Changing the size of the sequence') + + [Nx, Ny, Nz] = options['resize']['dim'] + [Sqx, Sqy, Sqz] = LOADsequences(options['resize']['loadseq']) + [Nx0, Ny0, Nz0, Nt] = Sqx.shape + + Sqx_new = np.zeros([Nx, Ny, Nz, Nt]) + Sqy_new = np.zeros([Nx, Ny, Nz, Nt]) + Sqz_new = np.zeros([Nx, Ny, Nz, Nt]) + + ax = int((Nx - Nx0)/2) + bx = ax + Nx0 + ay = int((Ny - Ny0)/2) + by = ay + Ny0 + az = int((Nz - Nz0)/2) + bz = az + Nz0 + + for t in range(Nt): + Sqx_new[ax:bx, ay:by, az:bz, t] = Sqx[:, :, :, t] + Sqy_new[ax:bx, ay:by, az:bz, t] = Sqy[:, :, :, t] + Sqz_new[ax:bx, ay:by, az:bz, t] = Sqz[:, :, :, t] + + if options['resize']['save']: + if rank == 0: + print('saving the sequences' + + options['resize']['savepath']) + np.savez_compressed( + options['resize']['savepath'], x=Sqx_new, y=Sqy_new, z=Sqz_new) + + if 'magnetization_CIB' in options: + if options['magnetization_CIB']['apply']: + if rank == 0: + print('-- Generating k-space for CIB phantom data-- ') + print('Using 0-G gradients') + + import Graphics + masterpath = options['magnetization_CIB']['loadpath'] + mask = Graphics.MATmedical(masterpath+'Segmented_Aorta.mat') + mask = mask.transpose((2, 0, 1)) + VENC = Graphics.MATmedical(masterpath+'VENC.mat') + VENC = VENC[0][0] + if rank == 0: + print('Recognized VENC = ' + str(VENC) + ' cm/s') + + # Magnitudes + magnitude_AP = Graphics.MATmedical(masterpath+'MR_FFE_AP.mat') + magnitude_FH = Graphics.MATmedical(masterpath+'MR_FFE_FH.mat') + magnitude_RL = Graphics.MATmedical(masterpath+'MR_FFE_RL.mat') + # Velocities + vel_AP = Graphics.MATmedical(masterpath+'MR_PCA_AP.mat') + vel_FH = Graphics.MATmedical(masterpath+'MR_PCA_FH.mat') + vel_RL = Graphics.MATmedical(masterpath+'MR_PCA_RL.mat') + + # Cropping images + a_crop = 48 + b_crop = 178 + mask = mask[:, :, a_crop:b_crop] + magnitude_AP = magnitude_AP[:, :, a_crop:b_crop, :] + vel_AP = vel_AP[:, :, a_crop:b_crop, :] + magnitude_RL = magnitude_RL[:, :, a_crop:b_crop, :] + vel_RL = vel_RL[:, :, a_crop:b_crop, :] + magnitude_FH = magnitude_FH[:, :, a_crop:b_crop, :] + vel_FH = vel_FH[:, :, a_crop:b_crop, :] + + # Reference phase + [Nx, Ny, Nz, Nt] = vel_AP.shape + gamma = 267.513e6 # rad/Tesla/sec Gyromagnetic ratio for H nuclei + B0 = 1.5 # Tesla Magnetic Field Strenght + TE = 5e-3 # Echo-time + [X, Y, Z] = np.meshgrid(np.linspace( + 0, Ny, Ny), np.linspace(0, Nx, Nx), np.linspace(0, Nz, Nz)) + frecX = 0.21 + p_ref = np.zeros([Nx, Ny, Nz]) + p_flow_AP = np.zeros([Nx, Ny, Nz]) + p_flow_RL = np.zeros([Nx, Ny, Nz]) + p_flow_FH = np.zeros([Nx, Ny, Nz]) + #Sx2G = np.zeros([Nx,Ny,Nz,Nt],dtype=complex) + #Sy2G = np.zeros([Nx,Ny,Nz,Nt],dtype=complex) + #Sz2G = np.zeros([Nx,Ny,Nz,Nt],dtype=complex) + Sx20 = np.zeros([Nx, Ny, Nz, Nt], dtype=complex) + Sy20 = np.zeros([Nx, Ny, Nz, Nt], dtype=complex) + Sz20 = np.zeros([Nx, Ny, Nz, Nt], dtype=complex) + + treshold = np.mean(magnitude_AP) + #p_ref = (gamma*B0*TE+frecX*X)*(np.abs(magnitude_AP[:,:,:,7])>treshold) + p_ref = (gamma*B0*TE+frecX*X)*(mask > 0.5) + + for t in range(Nt): + p_flow_AP = p_ref + np.pi*vel_AP[:, :, :, t]/VENC + p_flow_RL = p_ref + np.pi*vel_RL[:, :, :, t]/VENC + p_flow_FH = p_ref + np.pi*vel_FH[:, :, :, t]/VENC + + Sx20[:, :, :, t] = magnitude_AP[:, :, :, t] * \ + np.cos(p_ref) + 1j*magnitude_AP[:, :, :, t]*np.sin(p_ref) + Sy20[:, :, :, t] = magnitude_RL[:, :, :, t] * \ + np.cos(p_ref) + 1j*magnitude_RL[:, :, :, t]*np.sin(p_ref) + Sz20[:, :, :, t] = magnitude_FH[:, :, :, t] * \ + np.cos(p_ref) + 1j*magnitude_FH[:, :, :, t]*np.sin(p_ref) + + #Sx2G[:,:,:,t] = magnitude_AP[:,:,:,t]*np.cos(p_flow_AP) + 1j*magnitude_AP[:,:,:,t]*np.sin(p_flow_AP) + #Sy2G[:,:,:,t] = magnitude_RL[:,:,:,t]*np.cos(p_flow_RL) + 1j*magnitude_RL[:,:,:,t]*np.sin(p_flow_RL) + #Sz2G[:,:,:,t] = magnitude_FH[:,:,:,t]*np.cos(p_flow_FH) + 1j*magnitude_FH[:,:,:,t]*np.sin(p_flow_FH) + + if rank == 0: + print('saving the sequences' + + options['magnetization_CIB']['savepath']) + savepath = options['magnetization_CIB']['savepath'] + basepath = savepath.replace('.npz', '') + savepath0 = basepath + '0.npz' + savepathG = basepath + 'G.npz' + np.savez_compressed(savepath0, x=Sx20, y=Sy20, z=Sz20) + #np.savez_compressed(savepathG, x=Sx2G,y=Sy2G,z=Sz2G) + + if 'magnetization' in options: + if options['magnetization']['apply']: + if rank==0: + print('-- Generating k-space -- ') + print('Using 0-G gradients') + + [Sqx,Sqy,Sqz] = LOADsequences(options['magnetization']['loadseq']) + [Nx,Ny,Nz,Nt] = Sqx.shape + VENC = options['magnetization']['VENC'] + gamma = 267.513e6 # rad/Tesla/sec Gyromagnetic ratio for H nuclei + B0 = 1.5 # Tesla Magnetic Field Strenght + TE = 5e-3 # Echo-time + [X,Y,Z] = np.meshgrid(np.linspace(0,Ny,Ny),np.linspace(0,Nx,Nx),np.linspace(0,Nz,Nz)) + frecX = 0.21 # 0.21 without leaps: 0.01 + + Mx = np.zeros(Sqx.shape) + My = np.zeros(Sqx.shape) + Mz = np.zeros(Sqx.shape) + Sx2G = np.zeros(Sqx.shape,dtype=complex) + Sy2G = np.zeros(Sqx.shape,dtype=complex) + Sz2G = np.zeros(Sqx.shape,dtype=complex) + Sx20 = np.zeros(Sqx.shape,dtype=complex) + Sy20 = np.zeros(Sqx.shape,dtype=complex) + Sz20 = np.zeros(Sqx.shape,dtype=complex) + Fx0 = np.zeros(Sqx.shape) + Fy0 = np.zeros(Sqx.shape) + Fz0 = np.zeros(Sqx.shape) + FxG = np.zeros(Sqx.shape) + FyG = np.zeros(Sqx.shape) + FzG = np.zeros(Sqx.shape) + + # Creating M + for t in range(Nt): + Mx[:,:,:,t] = 0.05 + 0.9*(np.abs(Sqx[:,:,:,t])>0.001) + 0.05*np.sqrt(np.abs(Sqx[:,:,:,t])) + My[:,:,:,t] = 0.05 + 0.9*(np.abs(Sqy[:,:,:,t])>0.001) + 0.05*np.sqrt(np.abs(Sqy[:,:,:,t])) + Mz[:,:,:,t] = 0.05 + 0.9*(np.abs(Sqz[:,:,:,t])>0.001) + 0.05*np.sqrt(np.abs(Sqz[:,:,:,t])) + # Organs + Mx[:,:,:,t] = Mx[:,:,:,t] + 1*( (X-Ny/2)**2 + 0.75*(Y-Nx/2)**2 < 35**2 ) * ( (X-Ny/2)**2 + 0.75*(Y-Nx/2)**2 > 33**2 ) + Mx[:,:,:,t] = Mx[:,:,:,t] + 0.7*( 0.3*(X-Ny/2+9)**2 + 0.7*(Y-Nx/2-4)**2 < 3**2 )* ( np.abs(Z-Nz/2)<25 ) + My[:,:,:,t] = My[:,:,:,t] + 1*( (X-Ny/2)**2 + 0.75*(Y-Nx/2)**2 < 35**2 ) * ( (X-Ny/2)**2 + 0.75*(Y-Nx/2)**2 > 33**2 ) + My[:,:,:,t] = My[:,:,:,t] + 0.7*( 0.3*(X-Ny/2+9)**2 + 0.7*(Y-Nx/2-4)**2 < 3**2 )* ( np.abs(Z-Nz/2)<25 ) + Mz[:,:,:,t] = Mz[:,:,:,t] + 1*( (X-Ny/2)**2 + 0.75*(Y-Nx/2)**2 < 35**2 ) * ( (X-Ny/2)**2 + 0.75*(Y-Nx/2)**2 > 33**2 ) + Mz[:,:,:,t] = Mz[:,:,:,t] + 0.7*( 0.3*(X-Ny/2+9)**2 + 0.7*(Y-Nx/2-4)**2 < 3**2 )* ( np.abs(Z-Nz/2)<25 ) + FxG[:,:,:,t] = (gamma*B0*TE+frecX*X)*(np.abs(Mz[:,:,:,t])>0.4) + np.pi*Sqx[:,:,:,t]/VENC + FyG[:,:,:,t] = (gamma*B0*TE+frecX*X)*(np.abs(Mz[:,:,:,t])>0.4) + np.pi*Sqy[:,:,:,t]/VENC + FzG[:,:,:,t] = (gamma*B0*TE+frecX*X)*(np.abs(Mz[:,:,:,t])>0.4) + np.pi*Sqz[:,:,:,t]/VENC + Fx0[:,:,:,t] = (gamma*B0*TE+frecX*X)*(np.abs(Mz[:,:,:,t])>0.4) + Fy0[:,:,:,t] = (gamma*B0*TE+frecX*X)*(np.abs(Mz[:,:,:,t])>0.4) + Fz0[:,:,:,t] = (gamma*B0*TE+frecX*X)*(np.abs(Mz[:,:,:,t])>0.4) + + Sx20[:,:,:,t] = Mx[:,:,:,t]*np.cos(Fx0[:,:,:,t]) + 1j*Mx[:,:,:,t]*np.sin(Fx0[:,:,:,t]) + Sy20[:,:,:,t] = My[:,:,:,t]*np.cos(Fy0[:,:,:,t]) + 1j*My[:,:,:,t]*np.sin(Fy0[:,:,:,t]) + Sz20[:,:,:,t] = Mz[:,:,:,t]*np.cos(Fz0[:,:,:,t]) + 1j*Mz[:,:,:,t]*np.sin(Fz0[:,:,:,t]) + Sx2G[:,:,:,t] = Mx[:,:,:,t]*np.cos(FxG[:,:,:,t]) + 1j*Mx[:,:,:,t]*np.sin(FxG[:,:,:,t]) + Sy2G[:,:,:,t] = My[:,:,:,t]*np.cos(FyG[:,:,:,t]) + 1j*My[:,:,:,t]*np.sin(FyG[:,:,:,t]) + Sz2G[:,:,:,t] = Mz[:,:,:,t]*np.cos(FzG[:,:,:,t]) + 1j*Mz[:,:,:,t]*np.sin(FzG[:,:,:,t]) + + + # Adding noise by cartesian components + for t in range(Nt): + noise1 = np.random.normal(-0.0007,0.049,[Nx,Ny,Nz]) + noise2 = np.random.normal(-0.0007,0.049,[Nx,Ny,Nz]) + Sx20[:,:,:,t] += noise1 + 1j*noise2 + Sy20[:,:,:,t] += noise1 + 1j*noise2 + Sz20[:,:,:,t] += noise1 + 1j*noise2 + + noise1g = np.random.normal(-0.0007,0.049,[Nx,Ny,Nz]) + noise2g = np.random.normal(-0.0007,0.049,[Nx,Ny,Nz]) + Sx2G[:,:,:,t] += noise1g + 1j*noise2g + Sy2G[:,:,:,t] += noise1g + 1j*noise2g + Sz2G[:,:,:,t] += noise1g + 1j*noise2g + + + if rank==0: + print('saving the sequences' + options['magnetization']['savepath']) + savepath = options['magnetization']['savepath'] + basepath = savepath.replace('.npz','') + savepath0 = basepath + '0.npz' + savepathG = basepath + 'G.npz' + np.savez_compressed(savepath0, x=Sx20,y=Sy20,z=Sz20) + np.savez_compressed(savepathG, x=Sx2G,y=Sy2G,z=Sz2G) + + if 'sequence' in options: + if options['sequence']['apply']: + if rank == 0: + print('--- Creating Sequences ---') + + resol = options['sequence']['resol'] + boxsize = options['sequence']['boxsize'] + ranges = options['sequence']['ranges'] + BOX = LOADmesh(options['sequence']['boxtype'], resol=resol, boxsize=boxsize, ranges=ranges) + meshpath = options['sequence']['meshpath'] + AORTA = LOADmesh('aorta', meshpath=meshpath) + [Sqx, Sqy, Sqz] = CREATEsequences(BOX, AORTA, options) + + if 'norms' in options: + if options['norms']['apply']: + [BOX,AORTA,LEO] = CREATEmeshes(options) + if rank==0: + print('Computing Norms between fields') + ct_norm = checkpoint_norm(AORTA,options['norms']['field_path'],'ct') + kal_norm = checkpoint_norm(AORTA,options['norms']['field_path'],'roukf') + + if options['norms']['plot']: + import matplotlib.pyplot as plt + plt.plot(ct_norm, color='blue',marker='.',label='ct') + #plt.plot(meas_norm,label='meas') + plt.plot(kal_norm,color='green',label='kalman') + #plt.ylim([0,8500]) + plt.legend(fontsize=14) + plt.show() + + if 'CIBtoH5' in options: + print('---Converting CIB files into H5---') + if options['CIBtoH5']['apply']: + path_to_cib = options['CIBtoH5']['data_path'] + outpath = options['CIBtoH5']['outpath'] + times = options['CIBtoH5']['times'] + dt = options['CIBtoH5']['dt'] + flip = options['CIBtoH5']['flip'] + + if options['CIBtoH5']['interpolate']: + mesh_path = options['CIBtoH5']['mesh_path'] + CIBtoH5(path_to_cib,times,dt,outpath,interpolate=True,mesh_path=mesh_path,flip=flip) + else: + CIBtoH5(path_to_cib,times,dt,outpath,flip=flip) + + ######################################## + # + # Undersampling + # + ######################################## + if 'cs' in options: + if options['cs']['apply']: + if rank==0: + print('Applying Compressed Sensing') + + + [Sqx, Sqy, Sqz] = LOADsequences(options['cs']['seqpath']) + + + import CS + if options['cs']['short']: + [Mx,My,Mz] = LOADsequences(options['cs']['Mpath']) + CS.undersampling_short(Mx,My,Mz,options) + else: + CS.undersampling(Sqx,Sqy,Sqz,options,options['cs']['savepath']) + + if 'kt-BLAST' in options: + if options['kt-BLAST']['apply']: + if rank==0: + print('Applying kt-BLAST') + import ktBLAST + ktBLAST.undersampling(Sqx,Sqy,Sqz,options,options['kt-BLAST']['savepath']) + + if 'SENSE' in options: + if options['SENSE']['apply']: + if rank==0: + print('-- SENSE reconstruction --') + import SENSE + + [Mx,My,Mz] = LOADsequences(options['SENSE']['Mpath']) + [MxS,MyS,MzS] = SENSE.undersampling(Mx,My,Mz,options) + + if rank==0: + print('saving the sequences' + options['SENSE']['savepath']) + np.savez_compressed(options['SENSE']['savepath'], x=MxS,y=MyS,z=MzS) + + ######################################## + # + # Writing Checkpoint from Sequence + # + ######################################## + + if 'create_checkpoint' in options: + if options['create_checkpoint']['apply']: + print('--- Create Checkpoint ---') + + + mesh_into = options['create_checkpoint']['mesh_into'] + + + if options['create_checkpoint']['extension'] == '.mat': + import scipy.io as sio + seqpath = options['create_checkpoint']['loadseq'] + seqpath = seqpath + options['create_checkpoint']['seqname'] + seqpath = seqpath + '_R1.mat' + S = sio.loadmat(seqpath) + [ddx,ddy,ddz] = S['u_R1']['VoxelSize'][0][0][0] + [ddx,ddy,ddz] = [ddx/10,ddy/10,ddz/10] #mm to cm + S = S['u_R1'] + Sqx = S['x'][0][0] + [Lx,Ly,Lz,Lt] = Sqx.shape + BOX = LOADmesh('box_zeros', resol=[ddx,ddy,ddz], boxsize=[Lx,Ly,Lz]) + del S, Sqx, seqpath + else: + # Box mesh definition + boxsize = options['create_checkpoint']['boxsize'] + resol = options['create_checkpoint']['resol'] + ranges = options['create_checkpoint']['ranges'] + boxtype = options['create_checkpoint']['boxtype'] + if boxtype == 'fix_resolution': + BOX = LOADmesh(boxtype, resol=resol, boxsize=boxsize, ranges=ranges) + + + MESH = LOADmesh('other', meshpath=mesh_into) + + + for r in options['create_checkpoint']['Rseq']: + if rank == 0: + print('Writing checkpoint from sequence ' + + options['create_checkpoint']['seqname'] + '_R' + str(r) + '.npz') + + seqpath = options['create_checkpoint']['loadseq'] + options['create_checkpoint']['seqname'] + \ + '_R' + str(r) + options['create_checkpoint']['extension'] + + [Sx, Sy, Sz] = LOADsequences(seqpath) + + if options['create_checkpoint']['under_rate']>1: + print('Undersampling with factor: ', + options['create_checkpoint']['under_rate']) + Sx = Sx[:, :, :, 0::options['create_checkpoint']['under_rate']] + Sy = Sy[:, :, :, 0::options['create_checkpoint']['under_rate']] + Sz = Sz[:, :, :, 0::options['create_checkpoint']['under_rate']] + + if options['create_checkpoint']['masked']: + [S0x, S0y, S0z] = LOADsequences( + options['create_checkpoint']['masked_seq']) + [Sx, Sy, Sz] = MASKED([S0x, S0y, S0z], [Sx, Sy, Sz]) + del S0x, S0y, S0z + + vel_seq = SqtoH5(BOX, MESH, -Sx, Sy, -Sz) + #vel_seq = SqtoH5(BOX, MESH, Sx, Sy, Sz) + + if rank == 0: + print(' ') + + comm = MESH['mesh'].mpi_comm() + dt = options['create_checkpoint']['dt'] + if options['create_checkpoint']['xdmf']: + xdmf_u = XDMFFile(options['create_checkpoint']['savepath']+'u.xdmf') + + for l in range(len(vel_seq)): + if rank == 0: + print('saving checkpoint', l) + + path = options['create_checkpoint']['savepath'] + \ + 'R' + str(r) + '/checkpoint/{i}/'.format(i=l) + + if options['create_checkpoint']['xdmf']: + vel_seq[l].rename('velocity', 'u') + xdmf_u.write(vel_seq[l], l*dt) + + inout.write_HDF5_data( + comm, path + '/u.h5', vel_seq[l], '/u', t=l*dt) + + ######################################## + # + # Relative Pressure Estimators + # + ######################################## + if 'reference' in options: + if options['reference']['apply']: + if rank == 0: + print('---Applying Reference Pressure Gradient---') + + ckpath = options['reference']['checkpoint_path'] + under_rate = options['reference']['under_rate'] + MESH = LOADmesh('other', meshpath=options['reference']['meshpath']) + zeros = not 'ct' in ckpath + pressure = READcheckpoint( + MESH, 'p', ckpath, under_rate, 'p', zeros=zeros) + GradP(MESH, pressure, options) + + if 'ppe' in options: + + if options['ppe']['apply']: + [BOX,AORTA,LEO] = CREATEmeshes(options) + if rank==0: + print('Applying PPE') + if options['ppe']['mesh_type']=='aorta': + velocity_model = READcheckpoint(AORTA,'v',options,options['checkpoint_path'],'u') + if rank==0: + print(' ') + PPE(AORTA,velocity_model,options,options['ppe']['name']+ '.txt') + if rank==0: + print(' ') + + if options['ppe']['mesh_type']=='leo': + if not options['cs']['apply'] and not options['ppe']['read_check']: + raise Exception('You need first apply a CS sequence') + if options['ppe']['read_check']: + if options['meshname']=='leo': + velocity = READcheckpoint(LEO,'v',options,options['checkpoint_path'],'u') + MESH = LEO + if rank==0: + print(' ') + PPE(MESH,velocity,options,options['ppe']['name']+ '.txt') + if rank==0: + print(' ') + + + if not options['ppe']['read_check']: + for r in options['cs']['R']: + velocity[r] = SqtoH5(BOX,LEO,Sqx_cs[r],Sqy_cs[r],Sqz_cs[r]) + if rank==0: + print(' ') + PPE(LEO,velocity[r],options,options['ppe']['name']+options['ppe']['under_type']+'_R'+str(r)+'.txt') + if rank==0: + print(' ') + + if options['ppe']['mesh_type']=='leoct': + velocity_model = READcheckpoint(AORTA,'v',options,options['checkpoint_path'],'u') + if rank==0: + print(' ') + velocity_model_leo = CHANGEvel(LEO,velocity_model) + if rank==0: + print(' ') + PPE(LEO,velocity_model_leo,options,options['ppe']['name']+ '.txt') + if rank==0: + print(' ') + + if 'ste' in options: + + if options['ste']['apply']: + [BOX,AORTA,LEO] = CREATEmeshes(options) + if rank==0: + print('Applying STE') + + + if options['ste']['mesh_type']=='aorta': + if velocity_model: + STE(AORTA,velocity_model,options,options['ste']['name']+ '.txt') + else: + velocity_model = READcheckpoint(AORTA,'v',options,options['checkpoint_path'],'u') + + if rank==0: + print('') + + + if options['ste']['int']: + STEint(AORTA,velocity_model,options,options['ste']['name']+ '.txt') + else: + STE(AORTA,velocity_model,options,options['ste']['name']+ '.txt') + + if options['ste']['mesh_type']=='leo': + + if not options['cs']['apply'] and not options['ste']['read_check']: + raise Exception('You need first apply a CS sequence') + if options['ste']['read_check']: + if options['meshname']=='leo': + velocity = READcheckpoint(LEO,'v',options,options['checkpoint_path'],'u') + MESH = LEO + if rank==0: + print(' ') + + if options['ste']['int']: + STEint(MESH,velocity,options,options['ste']['name']+ '.txt') + else: + STE(MESH,velocity,options,options['ste']['name']+ '.txt') + if rank==0: + print(' ') + + if not options['ste']['read_check']: + for r in options['cs']['R']: + if velocity[r]: + STE(LEO,velocity[r],options,options['ste']['name']+options['ste']['under_type']+'_R'+str(r)+'.txt') + if rank==0: + print(' ') + else: + velocity[r] = SqtoH5(BOX,LEO,Sqx_cs[r],Sqy_cs[r],Sqz_cs[r]) + if rank==0: + print(' ') + if options['ste']['int']: + STEint(LEO,velocity[r],options,options['ste']['name']+options['ste']['under_type']+'_R'+str(r)+'.txt') + else: + STE(LEO,velocity[r],options,options['ste']['name']+options['ste']['under_type']+'_R'+str(r)+'.txt') + if rank==0: + print(' ') + + if options['ste']['mesh_type']=='leoct': + if velocity_model_leo: + STE(LEO,velocity_model_leo,options,options['ste']['name']+ '.txt') + if rank==0: + print(' ') + else: + velocity_model = READcheckpoint(AORTA,'v',options,options['checkpoint_path'],'u') + if rank==0: + print(' ') + velocity_model_leo = CHANGEvel(LEO,velocity_model) + if rank==0: + print(' ') + if options['ste']['int']: + STEint(LEO,velocity_model_leo,options,options['ste']['name']+ '.txt') + else: + STE(LEO,velocity_model_leo,options,options['ste']['name']+ '.txt') + if rank==0: + print(' ') + + if 'peak_pv' in options: + + if options['peak_pv']['apply']: + import CS + import pickle + import sys + import logging + # DPestim + logging.getLogger().setLevel(logging.INFO) + parameters['form_compiler']['optimize'] = True + parameters['form_compiler']['cpp_optimize'] = True + parameters['form_compiler']['cpp_optimize_flags'] = '-O3 -ffast-math -march=native' + infile_dp = options['peak_pv']['infile_dp'] + estimator = DPDirectEstim(infile_dp) + + barye2mmHg = 1/1333.22387415 + t_star = 0.185 + if rank==0: + print('Computing Velocity and Pressure at Peak Systole') + print('The inlet max occurs at ' + str(t_star) + ' sec') + + + [BOX,AORTA,LEO] = CREATEmeshes(options) + + if options['peak_pv']['mesh_into']=='leo': + MESH = LEO + del AORTA + if options['peak_pv']['mesh_into']=='aorta': + MESH = AORTA + del LEO + + if options['peak_pv']['p_comp']=='error': + if rank==0: + print('Reading Pressure Reference') + P0_PPE = READcheckpoint(MESH,'p',options,options['checkpoint_path'],'p_PPE_impl_stan') + P0_STE = READcheckpoint(MESH,'p',options,options['checkpoint_path'],'p_STE_impl_stan') + + [Sqx,Sqy,Sqz] = LOADsequences(options['peak_pv']['orig_seq']) + Nite = options['peak_pv']['N_CS'] + [row,col,dep,numt] = Sqz.shape + frms_num = 3 + peakslice = options['peak_pv']['peak_slice'] + R = options['peak_pv']['R'] + + v0 = np.sqrt(Sqx[:,:,:,peakslice]**2 + Sqy[:,:,:,peakslice]**2 + Sqz[:,:,:,peakslice]**2) + max0 = np.where(v0==np.max(v0)) + + qqvec = {} + for ss in options['peak_pv']['flux_bnd']: + qqvec[ss] = np.zeros([Nite]) + + ppemax = np.zeros([Nite]) + stemax = np.zeros([Nite]) + vmax = np.zeros([Nite]) + slrdmax = peakslice + # Selecting around the max only + slrdmax = 1 + Sqx = Sqx[:,:,:,peakslice-1:peakslice+2] + Sqy = Sqy[:,:,:,peakslice-1:peakslice+2] + Sqz = Sqz[:,:,:,peakslice-1:peakslice+2] + + for l in range(len(R)): + if rank==0: + print('Peak Systole velocity and pressure at R = ' + str(R[l])) + + sx_cs = np.zeros([row,col,dep,frms_num,Nite]) + sy_cs = np.zeros([row,col,dep,frms_num,Nite]) + sz_cs = np.zeros([row,col,dep,frms_num,Nite]) + + for k in range(Nite): + if rank==0: + print('CS iteration number ' + str(k+1)) + [xcs,ycs,zcs] = CS.undersampling_peakpv(Sqx,Sqy,Sqz,options,R[l]) + sx_cs[:,:,:,:,k] = xcs + sy_cs[:,:,:,:,k] = ycs + sz_cs[:,:,:,:,k] = zcs + vk = np.sqrt(sx_cs[:,:,:,1,k]**2 + sy_cs[:,:,:,1,k]**2 + sz_cs[:,:,:,1,k]**2) + vmax[k] = vk[max0] + + if rank==0: + print('\n CS done') + + # To write the checkpoints + vel_seq = SqtoH5(BOX,MESH,sx_cs[:,:,:,:,k],sy_cs[:,:,:,:,k],sz_cs[:,:,:,:,k]) + comm = MESH['mesh'].mpi_comm() + + # Computing the Fluxes + if rank==0: + print('\n Computing the Flux') + QQ = Fluxes(MESH,vel_seq,options,options['peak_pv']['flux_bnd']) + + for ss in options['peak_pv']['flux_bnd']: + qqvec[ss][k] = QQ[ss][slrdmax] + + if rank==0: + print('\n Writing checkpoints') + + for ns in range(len(vel_seq)): + pathss = options['peak_pv']['savepath'] + 'H5/checkpoint/{i}/'.format(i=ns) + if l<10 and l>0: + pathss = options['peak_pv']['savepath'] + 'H5/checkpoint/0{i}/'.format(i=ns) + inout.write_HDF5_data(comm, pathss + '/u.h5', vel_seq[ns], '/u', t=0) + if rank==0: + print('\n The checkpoints were wrote') + + # Computing the Pressure Drop + estimator.estimate() + # Reading the results + if options['peak_pv']['p_comp']=='peak': + ppe_raw = open(options['peak_pv']['savepath'] + '/H5/pdrop_PPE_impl_stan.dat','rb') + ste_raw = open(options['peak_pv']['savepath'] + '/H5/pdrop_STE_impl_stan.dat','rb') + ppe = pickle.load(ppe_raw)['pdrop']*(-barye2mmHg) + ste = pickle.load(ste_raw)['pdrop']*(-barye2mmHg) + p1max[k] = ppe[slrdmax] + p2max[k] = ste[slrdmax] + elif options['peak_pv']['p_comp']=='error': + PPE = READcheckpoint(MESH,'p',options,options['peak_pv']['savepath']+'H5/checkpoint/','p_PPE_impl_stan') + STE = READcheckpoint(MESH,'p',options,options['peak_pv']['savepath']+'H5/checkpoint/','p_STE_impl_stan') + ppe_vec_0 = P0_PPE[peakslice].vector().get_local() - P0_PPE[peakslice].vector().get_local()[0] + ppe_vec = PPE[slrdmax].vector().get_local() - PPE[slrdmax].vector().get_local()[0] + ste_vec_0 = P0_STE[peakslice].vector().get_local() - P0_STE[peakslice].vector().get_local()[0] + ste_vec = STE[slrdmax].vector().get_local() - STE[slrdmax].vector().get_local()[0] + ppemax[k] = np.linalg.norm(ppe_vec_0 - ppe_vec)/np.linalg.norm(ppe_vec_0) + stemax[k] = np.linalg.norm(ste_vec_0 - ste_vec)/np.linalg.norm(ste_vec_0) + else: + raise Exception('Pressure computation not recognize!') + + + # VELOCITIES + vmean = np.mean(vmax) + vstd = np.std(vmax) + # PRESSURES + ppemean = np.mean(ppemax) + stemean = np.mean(stemax) + ppestd = np.std(ppemax) + stestd = np.std(stemax) + + + if options['peak_pv']['save']: + if rank==0: + print('\n saving the files in ' + options['peak_pv']['savepath']) + for ss in options['peak_pv']['flux_bnd']: + np.savetxt( options['peak_pv']['savepath'] + 'Q'+str(ss) +'_R'+str(R[l])+'.txt', [np.mean(qqvec[ss])]) + np.savetxt( options['peak_pv']['savepath'] + 'Qstd'+str(ss) +'_R'+str(R[l])+'.txt', [np.std(qqvec[ss])]) + np.savetxt( options['peak_pv']['savepath'] + 'ppemean_R'+str(R[l])+'.txt', [ppemean] ) + np.savetxt( options['peak_pv']['savepath'] + 'stemean_R'+str(R[l])+'.txt', [stemean] ) + np.savetxt( options['peak_pv']['savepath'] + 'vmean_R'+str(R[l])+'.txt', [vmean] ) + np.savetxt( options['peak_pv']['savepath'] + 'ppestd_R'+str(R[l])+'.txt', [ppestd] ) + np.savetxt( options['peak_pv']['savepath'] + 'stestd_R'+str(R[l])+'.txt', [stestd] ) + np.savetxt( options['peak_pv']['savepath'] + 'vstd_R'+str(R[l])+'.txt', [vstd] ) + + if 'change_mesh' in options: + if options['change_mesh']['apply']: + if rank == 0: + print('Changing '+options['change_mesh']['mode'] + ' from: ') + print('Mesh input: ' + options['change_mesh']['mesh_in']) + print('Mesh output: ' + options['change_mesh']['mesh_out']) + + MESH_in = LOADmesh( + 'other', meshpath=options['change_mesh']['mesh_in']) + MESH_out = LOADmesh( + 'other', meshpath=options['change_mesh']['mesh_out']) + + ckpath = options['change_mesh']['checkpoint_path'] + under_rate = options['change_mesh']['under_rate'] + mode = options['change_mesh']['mode'] + + origin = READcheckpoint(MESH_in, mode, ckpath, under_rate, mode, zeros=False) + + # To change between meshes the same result + changed = {} + #W = LEO['FEM'].sub(0).collapse() + comm = MESH_out['mesh'].mpi_comm() + v2 = Function(MESH_out['FEM']) + + for k in range(len(list(origin))): + if rank == 0: + print('CHANGING: index', k) + LagrangeInterpolator.interpolate(v2, origin[k]) + changed[k] = v2 + print(max(origin[k].vector().get_local()),max(v2.vector().get_local())) + + + dt = options['change_mesh']['dt'] + if options['create_checkpoint']['xdmf']: + xdmf_u = XDMFFile(options['change_mesh']['savepath']+'u.xdmf') + for l in range(len(changed)): + if rank == 0: + print('saving checkpoint', l) + path = options['change_mesh']['savepath'] + \ + 'R1/checkpoint/{i}/'.format(i=l) + writepath = path + '/'+options['change_mesh']['mode']+'.h5' + inout.write_HDF5_data( + comm, writepath, changed[l] ,'/'+options['change_mesh']['mode'], t=l*dt) + + if options['create_checkpoint']['xdmf']: + changed[l].rename('velocity', 'u') + xdmf_u.write(changed[l], l*dt) + + + +if __name__ == '__main__': + + comm = MPI.COMM_WORLD + size = comm.Get_size() + rank = comm.Get_rank() + + if len(sys.argv) > 1: + if os.path.exists(sys.argv[1]): + inputfile = sys.argv[1] + if rank==0: + print('Found input file ' + inputfile) + else: + Etcetera('serious') + raise Exception('Command line arg given but input file does not exist:' + ' {}'.format(sys.argv[1])) + else: + Etcetera('serious') + raise Exception('An input file is required as argument!') + + + user = 'p283370' # Default's user + if 'Zion' in os.popen('hostname').read(): + user = 'yeye' + np.set_printoptions(threshold=5) + + if 'fwn-bborg-5-166' in os.popen('hostname').read(): + user = 'p283370' + + if rank==0: + print('Welcome user {uss}'.format(uss=user)) + Etcetera('happy') + + + start_time = time.time() + + options = inout.read_parameters(inputfile) + SCANNER(options) + + end_time = time.time() + CLOCK(rank,start_time,end_time) + diff --git a/codes/PostCheck.py b/codes/PostCheck.py new file mode 100644 index 0000000..1674730 --- /dev/null +++ b/codes/PostCheck.py @@ -0,0 +1,1072 @@ +from dolfin import * +import numpy as np +import sys +import os +from mpi4py import MPI +from common import inout + + +def LOADmesh(pathtomesh): + + mesh = Mesh() + hdf = HDF5File(mesh.mpi_comm(), pathtomesh, 'r') + hdf.read(mesh, '/mesh', False) + boundaries = MeshFunction('size_t', mesh, mesh.topology().dim() - 1) + hdf.read(boundaries, '/boundaries') + + #Evel = VectorElement('P',mesh.ufl_cell(),1) + #V = FunctionSpace(mesh,Evel) + + #V1 = VectorElement('P', mesh.ufl_cell(), 1) + #V = FunctionSpace(mesh, V1) + P1 = FiniteElement('P', mesh.ufl_cell(), 1) + V1 = VectorElement('P', mesh.ufl_cell(), 1) + V = FunctionSpace(mesh, V1*P1) + + if rank == 0: + print('MESH ' + ' created: H = ' + + str(mesh.hmin()) + ' H_max = ' + str(mesh.hmax())) + + MESH = {} + MESH['mesh'] = mesh + MESH['FEM'] = V + MESH['boundaries'] = boundaries + + return MESH + +def LOADsequences(loadpath): + # for loading existing sequences alocated in loadpath + if rank == 0: + print('{reading} ' + loadpath) + S = np.load(loadpath) + Sqx = S['x'] + Sqy = S['y'] + Sqz = S['z'] + return [Sqx, Sqy, Sqz] + +def WORKcheck(MESH, mode, output_path, checkpoint_path, filename, outname, options): + + #from dolfin import HDF5File + V = MESH['FEM'] + W = MESH['FEM'].sub(0).collapse() + # Checkpoints folders + unsort_indexes = os.listdir(checkpoint_path) + indexes = [int(x) for x in unsort_indexes] + indexes.sort() + + + if mode == 'u': + v = Function(W) + xdmf_u = XDMFFile(output_path+outname+'.xdmf') + dt = options['Velocity']['dt'] + for k in range(0,len(indexes),options['Velocity']['undersampling']): + te = k*dt + path = checkpoint_path + str(indexes[k]) + '/'+filename+'.h5' + v.rename('velocity', outname) + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + if 'w' in filename: + hdf.read(v, 'w/vector_0') + else: + hdf.read(v, 'u/vector_0') + hdf.close() + xdmf_u.write(v, te) + + if mode == 'w': + xdmf_u = XDMFFile(output_path+outname+'.xdmf') + for k in range(0, len(indexes), 1): + path = checkpoint_path + str(indexes[k]) + '/'+filename+'.h5' + v = Function(V) + v.rename('waux', outname) + comm = MPI.COMM_WORLD + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(v, 'w/vector_0') + hdf.close() + wvec = v.vector().get_local() + wnorm = wvec - np.mean(wvec) + v.vector()[:] = wnorm + xdmf_u.write(v, te) + te = te + dt + numt = numt + 1 + + if mode == 'gradw': + xdmf_u = XDMFFile(output_path+outname+'.xdmf') + for k in range(0, len(indexes), 1): + path = checkpoint_path + str(indexes[k]) + '/'+filename+'.h5' + v = Function(V) + gw = Function(W) + gw.rename(outname, outname) + comm = MPI.COMM_WORLD + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(v, 'w/vector_0') + hdf.close() + wvec = v.vector().get_local() + wnorm = wvec - np.mean(wvec) + v.vector()[:] = wnorm + gw.assign(project(sqrt(inner(grad(v), grad(v))), W)) + xdmf_u.write(gw, te) + te = te + dt + numt = numt + 1 + + if mode == 'p' or mode == 'p_cib': + xdmf_p = XDMFFile(output_path+outname+'.xdmf') + for k in range(0, len(indexes), 1): + path = checkpoint_path + str(indexes[k]) + '/'+filename+'.h5' + + if filename == 'p': + if k < 10 and k > 0: + path = checkpoint_path + '0' + \ + str(indexes[k]) + '/'+filename+'.h5' + + p = Function(W) + if mode == 'p': + barye2mmHg = 1/1333.22387415 + if mode == 'p_cib': + barye2mmHg = -0.00750062 + p.rename('pressure', outname) + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(p, 'p/vector_0') + hdf.close() + + p1vec = p.vector().get_local() + p1vec = p1vec - np.mean(p1vec) + p.vector()[:] = p1vec*barye2mmHg + xdmf_p.write(p, te) + te = te + dt + numt = numt + 1 + + if mode == 'divu': + xdmf_u = XDMFFile(output_path+outname+'.xdmf') + for k in range(0, len(indexes), 1): + path = checkpoint_path + str(indexes[k]) + '/'+filename+'.h5' + + if indexes[k] < 10 and indexes[k] > 0: + path = checkpoint_path + '0' + \ + str(indexes[k]) + '/'+filename+'.h5' + + v = Function(V) + dv = Function(W) + + dv.rename('div', outname) + comm = MPI.COMM_WORLD + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(v, 'u/vector_0') + + hdf.close() + dv.assign(project(div(v), W)) + xdmf_u.write(dv, te) + te = te + dt + numt = numt + 1 + +def READcheckpoint(MESH, mode, output_path, checkpoint_path, filename, outname, options, flow=False, bnds=None): + + #from dolfin import HDF5File + V = MESH['FEM'] + W = MESH['FEM'].sub(0).collapse() + # Checkpoints folders + unsort_indexes = os.listdir(checkpoint_path) + indexes = [int(x) for x in unsort_indexes] + indexes.sort() + + if flow: + QQ = {} + ds = Measure('ds', domain=MESH['mesh'], + subdomain_data=MESH['boundaries']) + n = FacetNormal(MESH['mesh']) + for bb in bnds: + QQ[bb] = [] + + + if mode == 'interpolation': + dt_new = options['Temporal-Interpolation']['dt_new'] + dt = options['Temporal-Interpolation']['dt'] + Nfolder = len(indexes) + Tf = dt*(Nfolder-1) + Nfolder_new = np.int(Tf/dt_new + 1) + indexes_new = [k for k in range(1,Nfolder_new+1)] + + u = Function(W) + unew = Function(W) + u.rename('velocity', outname) + unew.rename('velocity', outname) + + if options['Temporal-Interpolation']['xdmf']: + xdmf_u = XDMFFile(output_path+'u.xdmf') + + uvec = {} + # Reading first all the points for every original time-steps + for k in indexes: + path = checkpoint_path + str(k) + '/'+filename+'.h5' + print('Reading timestep number: ' + str(k)) + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + if 'w' in filename: + hdf.read(u, 'w/vector_0') + else: + hdf.read(u, 'u/vector_0') + hdf.close() + uvec[k] = u.vector().get_local() + + times_old = np.linspace(0,Tf,Nfolder) + times_new = np.linspace(0,Tf,Nfolder_new) + velnodes = np.zeros(times_old.size) + velnodes_new = np.zeros(times_new.size) + uvec_new = {} + + for k in indexes_new: + uvec_new[k] = np.zeros(uvec[1].size) + + from scipy.interpolate import interp1d + print('Interpolating in every node across time') + # FOR every single node!!! + for l in range(len(uvec[1])): + for k in range(len(velnodes)): + velnodes[k] = uvec[indexes[k]][l] + inter_f = interp1d(times_old, velnodes , kind='cubic') + velnodes_new = inter_f(times_new) + for k in range(len(velnodes_new)): + uvec_new[indexes_new[k]][l] = velnodes_new[k] + print('Interpolation done') + + for k in indexes_new: + print('Writing timestep number: ' + str(k) ) + + unew.vector()[:] = uvec_new[k][:] + + write_path = output_path + 'checkpoint/{i}/'.format(i=k) + hdf2 = HDF5File(MESH['mesh'].mpi_comm(), write_path + 'u.h5', 'w') + hdf2.write(unew, '/u', float((k-1)*dt_new)) + hdf2.close() + + if options['Temporal-Interpolation']['xdmf']: + xdmf_u.write(unew, (k-1)*dt_new) + + + if mode == 'average': + N_av = options['Temporal-Average']['subsampling_rate'] + dt = options['Temporal-Average']['dt'] + ks = 1 + mean_fill = False + u = Function(W) + usub = Function(W) + u.rename('velocity', outname) + usub.rename('velocity', outname) + if options['Temporal-Average']['xdmf']: + xdmf_u = XDMFFile(output_path+'test.xdmf') + + for k in range(len(indexes)): + path = checkpoint_path + str(indexes[k]) + '/'+filename+'.h5' + print('Reading timestep number: ' + str(indexes[k])) + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + if 'w' in filename: + hdf.read(u, 'w/vector_0') + else: + hdf.read(u, 'u/vector_0') + hdf.close() + + if not mean_fill: + mean_u = u.vector().get_local()/N_av + mean_fill = True + else: + mean_u += u.vector().get_local()/N_av + + if np.mod(k+1,N_av) == 0: + mean_fill = False + usub.vector()[:] = mean_u + print('saving timestep number: ' , ks) + write_path = output_path + 'checkpoint/{i}/'.format(i=ks) + hdf2 = HDF5File(MESH['mesh'].mpi_comm(), write_path + 'u.h5', 'w') + hdf2.write(usub, '/u', float((k-N_av+1)*dt)) + hdf2.close() + if options['Temporal-Average']['xdmf']: + xdmf_u.write(usub, (k-N_av+1)*dt) + ks +=1 + + if mode == 'u': + xdmf_u = XDMFFile(output_path+outname+'.xdmf') + for k in range(0, len(indexes), 1): + path = checkpoint_path + str(indexes[k]) + '/'+filename+'.h5' + u = Function(V) + u.rename('velocity', outname) + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(u, 'u/vector_0') + hdf.close() + if flow: + for bb in bnds: + QQ[bb].append(assemble(dot(u, n)*ds(bb))) + + xdmf_u.write(u, k) + te = te + dt + + if flow: + for bb in bnds: + np.savetxt(output_path+'flowrate'+str(bb)+'.txt', QQ[bb]) + + if mode == 'w': + xdmf_u = XDMFFile(output_path+outname+'.xdmf') + for k in range(0, len(indexes), 1): + path = checkpoint_path + str(indexes[k]) + '/'+filename+'.h5' + v = Function(V) + v.rename('waux', outname) + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(v, 'w/vector_0') + hdf.close() + wvec = v.vector().get_local() + wnorm = wvec - np.mean(wvec) + v.vector()[:] = wnorm + xdmf_u.write(v, k) + + if mode == 'gradw': + xdmf_u = XDMFFile(output_path+outname+'.xdmf') + for k in range(0, len(indexes), 1): + path = checkpoint_path + str(indexes[k]) + '/'+filename+'.h5' + v = Function(V) + gw = Function(W) + gw.rename(outname, outname) + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(v, 'w/vector_0') + hdf.close() + wvec = v.vector().get_local() + wnorm = wvec - np.mean(wvec) + v.vector()[:] = wnorm + gw.assign(project(sqrt(inner(grad(v), grad(v))), W)) + xdmf_u.write(gw, k) + + if mode == 'p' or mode == 'p_cib': + xdmf_p = XDMFFile(output_path+outname+'.xdmf') + for k in range(0, len(indexes), 1): + path = checkpoint_path + str(indexes[k]) + '/'+filename+'.h5' + p = Function(W) + if mode == 'p': + barye2mmHg = -1/1333.22387415 + if mode == 'p_cib': + barye2mmHg = -0.00750062 + p.rename('pressure', outname) + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(p, 'p/vector_0') + hdf.close() + p1vec = p.vector().get_local()*barye2mmHg + p.vector()[:] = p1vec + xdmf_p.write(p, k) + + if mode == 'divu': + xdmf_u = XDMFFile(output_path+outname+'.xdmf') + for k in range(0, len(indexes), 1): + path = checkpoint_path + str(indexes[k]) + '/'+filename+'.h5' + v = Function(V) + dv = Function(W) + dv.rename('div', outname) + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(v, 'u/vector_0') + hdf.close() + dv.assign(project(div(v), W)) + xdmf_u.write(dv, k) + +def ERRORmap(MESH, mode, outpath, reference_path, checkpoint_path, refname,comname,options): + + from dolfin import HDF5File + V = MESH['FEM'] + W = MESH['FEM'].sub(0).collapse() + unsort_indexes = os.listdir(checkpoint_path) + indexes = [int(x) for x in unsort_indexes] + indexes.sort() + unsort_indexes0 = os.listdir(reference_path) + indexes0 = [int(x) for x in unsort_indexes0] + indexes0.sort() + + + if len(indexes)!=len(indexes0): + raise Exception('The lengh of the checkpoints are not the same!') + + if mode =='curves': + + if options['Error-curves']['undersampling']>1: + print('undersampling in the reference measurements!') + n_under = options['Error-curves']['undersampling'] + indexes0 = indexes0[0::n_under] + + u = Function(W) + w = Function(W) + for typs in options['Error-curves']['type']: + ucomp = [] + wcomp = [] + times = [] + dt = options['Error-curves']['dt'] + for k in range(1,len(indexes)): + path_w = checkpoint_path + str(indexes[k]) + '/'+comname+'.h5' + path_u = reference_path + str(indexes0[k]) + '/'+refname+'.h5' + + u.rename('meas', 'meas') + w.rename('w', 'w') + hdf_w = HDF5File(MESH['mesh'].mpi_comm(),path_w,'r') + hdf_w.read(w, 'w/vector_0') + hdf_u = HDF5File(MESH['mesh'].mpi_comm(), path_u, 'r') + hdf_u.read(u, 'u/vector_0') + hdf_u.close() + hdf_w.close() + u_vec = u.vector().get_local() + w_vec = w.vector().get_local() + print('computing error in timestep numer',k) + + if typs == 'mean': + ucomp.append(np.mean(abs(u_vec))) + wcomp.append(np.mean(abs(w_vec))) + elif typs == 'max': + ucomp.append(np.max(abs(u_vec))) + wcomp.append(np.max(abs(w_vec))) + else: + raise Exception('No defined type for curve printing!') + + times.append(k*dt) + + np.savetxt(outpath+'u' +typs+'.txt',ucomp) + np.savetxt(outpath+'w' +typs+'.txt',wcomp) + np.savetxt(outpath+'times.txt',times) + + if mode == 'histogram': + from pathlib import Path + import pickle + u = Function(V) + w = Function(V) + errors = {} + + for k in range(len(indexes)): + path_w = checkpoint_path + str(indexes[k]) + '/'+comname+'.h5' + path_u = reference_path + str(indexes0[k]) + '/'+refname+'.h5' + + if indexes0[k] < 10: + path_u = reference_path + '0' + \ + str(indexes0[k]) + '/'+refname+'.h5' + + u.rename('meas', 'meas') + w.rename('w', 'w') + hdf_w = HDF5File(MESH['mesh'].mpi_comm(),path_w,'r') + hdf_w.read(w, 'w/vector_0') + hdf_u = HDF5File(MESH['mesh'].mpi_comm(), path_u, 'r') + hdf_u.read(u, 'u/vector_0') + hdf_u.close() + hdf_w.close() + + u_vec = u.vector().get_local() + w_vec = w.vector().get_local() + errors[k] = np.zeros(u_vec.size) + + for l in range(len(errors[k])): + #errors[k][l] = np.nan + if u_vec[l]<1e-9: + errors[k][l] = -1 + else: + eta = np.abs(w_vec[l]/u_vec[l]) + if np.abs(eta)>50: + errors[k][l] = -1 + else: + errors[k][l] = eta + + + write_path = Path(outpath) + fpath = write_path.joinpath('errors.dat') + pickle.dump(errors, fpath.open('wb')) + + if mode == 'h5': + xdmf_u = XDMFFile(outpath+'meas.xdmf') + #xdmf_ucor = XDMFFile(output_path+'ucor.xdmf') + xdmf_w = XDMFFile(outpath+'w.xdmf') + ds = Measure("ds", subdomain_data=MESH['boundaries']) + + u = Function(W) + w = Function(W) + #ucor = Function(W) + + for k in range(0, len(indexes), 1): + path_w = checkpoint_path + str(indexes[k]) + '/'+comname+'.h5' + path_u = reference_path + str(indexes0[k]) + '/'+refname+'.h5' + + if indexes0[k] < 10: + path_u = reference_path + '0' + \ + str(indexes0[k]) + '/'+refname+'.h5' + + u.rename('meas', 'meas') + w.rename('w', 'w') + #ucor.rename('ucor', 'ucor') + hdf_w = HDF5File(MESH['mesh'].mpi_comm(),path_w,'r') + hdf_w.read(w, 'w/vector_0') + hdf_u = HDF5File(MESH['mesh'].mpi_comm(), path_u, 'r') + hdf_u.read(u, 'u/vector_0') + + hdf_u.close() + hdf_w.close() + + #u_vec = u.vector().get_local() + #w_vec = w.vector().get_local() + #ucor.vector()[:] = u_vec + w_vec + + xdmf_u.write(u, k) + #xdmf_ucor.write(ucor, k) + xdmf_w.write(w, k) + + if mode == 'colormap': + colormap = XDMFFile(outpath+'colormap.xdmf') + #ds = Measure("ds", subdomain_data=MESH['boundaries']) + u = Function(W) + w = Function(W) + cm = Function(W) + dt = options['Corrector']['dt'] + + for k in range(len(indexes)): + print('making the colormap in the time',np.round(k*dt,2)) + path_w = checkpoint_path + str(indexes[k]) + '/'+comname+'.h5' + path_u = reference_path + str(indexes0[k]) + '/'+refname+'.h5' + u.rename('meas', 'meas') + w.rename('w', 'w') + cm.rename('color','color') + hdf_w = HDF5File(MESH['mesh'].mpi_comm(),path_w,'r') + hdf_w.read(w, 'w/vector_0') + hdf_u = HDF5File(MESH['mesh'].mpi_comm(), path_u, 'r') + hdf_u.read(u, 'u/vector_0') + hdf_u.close() + hdf_w.close() + uvec = u.vector().get_local() + wvec = w.vector().get_local() + cm.vector()[:] = np.sqrt((uvec - wvec)**2) + colormap.write(cm, k*dt) + + if mode == 'error_u': + xdmf_u = XDMFFile(output_path+'error_u.xdmf') + for k in range(0, len(indexes), 1): + path = checkpoint_path + str(indexes[k]) + '/'+comname+'.h5' + path0 = reference_path + str(indexes0[k]) + '/'+refname+'.h5' + + if k < 10: + path = checkpoint_path + '0'+str(indexes[k]) + '/u.h5' + path0 = reference_path + '0'+str(indexes[k]) + '/u.h5' + + u = Function(V) + u0 = Function(V) + + eu = Function(W) + eu.rename('error_u', 'error_u') + + comm = MPI.COMM_WORLD + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(u, 'u/vector_0') + hdf0 = HDF5File(MESH['mesh'].mpi_comm(), path0, 'r') + hdf0.read(u0, 'u/vector_0') + hdf0.close() + hdf.close() + + eu.assign(project(sqrt(inner(u-u0, u-u0)), W)) + + xdmf_u.write(eu, te) + te = te + dt + numt = numt + 1 + + if mode == 'error_p' or mode == 'error_p_cib': + xdmf_p = XDMFFile(output_path+outname+'.xdmf') + for k in range(0, len(indexes0), 1): + path = checkpoint_path + str(indexes[k]) + '/'+comname+'.h5' + path0 = reference_path + str(indexes0[k]) + '/'+refname+'.h5' + + if refname == 'p': + if k < 10 and k > 0: + path0 = reference_path + '0' + \ + str(indexes0[k]) + '/'+refname+'.h5' + + #zero_point = [12.79353, 14.32866, 6.51101] + #zero_point = np.array(zero_point) + #ndim = W.mesh().topology().dim() + #zero_point = W.tabulate_dof_coordinates().reshape((-1, ndim))[0] + + if 'cib' in mode: + barye2mmHg = 0.00750062 + else: + barye2mmHg = 1/1333.22387415 + p = Function(W) + p0 = Function(W) + + p.rename('error_p', outname) + + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(p, 'p/vector_0') + hdf0 = HDF5File(MESH['mesh'].mpi_comm(), path0, 'r') + hdf0.read(p0, 'p/vector_0') + + hdf.close() + hdf0.close() + + #p0.vector()[:] -= p0(zero_point) + pvec = p.vector().get_local() + p0vec = p0.vector().get_local() + + pvec = pvec - np.mean(pvec) + p0vec = p0vec - np.mean(p0vec) + + errvec = np.sqrt((pvec - p0vec)**2)*barye2mmHg + #errvec = np.abs((pvec - p0vec)/(p0vec)) + + p.vector()[:] = errvec + #p.vector()[:] = p0vec + + xdmf_p.write(p, te) + te = te + dt + numt = numt + 1 + +def SEQCIBH5(pathtocib, pathtocibseq, ndata): + + import csv + + times = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] + #times = [8] + + if ndata == 1: + pathtocib += '9_mm_AoCo_phantom_rest_vox0.9mm/' + pathtocibseq += '9AoCo_rest_vox0.9/' + elif ndata == 2: + pathtocib += '9_mm_AoCo_phantom_stress_vox0.9mm/' + pathtocibseq += '9AoCo_stress_vox0.9/' + elif ndata == 3: + pathtocib += '11_mm_AoCo_phantom_rest_vox0.9mm/' + pathtocibseq += '11AoCo_rest_vox0.9/' + elif ndata == 4: + pathtocib += '11_mm_AoCo_phantom_stress_vox0.9mm/' + pathtocibseq += '11AoCo_stress_vox0.9/' + else: + raise Exception('Data file not recognize!') + + xdmf_v = XDMFFile(pathtocibseq + 'vel.xdmf') + + mesh = Mesh(pathtocib+'aorta.xml') + Evel = VectorElement('Lagrange', mesh.ufl_cell(), 1) + V = FunctionSpace(mesh, Evel) + boundaries = MeshFunction("size_t", mesh, mesh.topology().dim()-1) + + VX = V.sub(0).collapse() + VY = V.sub(1).collapse() + VZ = V.sub(2).collapse() + vv_x = Function(VX) + vv_y = Function(VY) + vv_z = Function(VZ) + v = Function(V) + + v.rename('velocity', 'vel') + mx = dof_to_vertex_map(VX) + my = dof_to_vertex_map(VY) + mz = dof_to_vertex_map(VZ) + + for ti in times: + print('reading aorta '+str(ti) + '.csv') + with open(pathtocib + 'aorta'+str(ti)+'.csv', 'r') as csvfile: + mylist = [row[0] for row in csv.reader(csvfile, delimiter=';')] + + Values = np.array(mylist) + file_x = np.zeros([len(Values)]) + file_y = np.zeros([len(Values)]) + file_z = np.zeros([len(Values)]) + + for l in range(len(Values)): + row = Values[l].split(',') + file_x[l] = float(row[0]) + file_y[l] = float(row[1]) + file_z[l] = float(row[2]) + + # print(np.max(file_z)) + #print(np.where(file_z==np.max(file_z)) ) + # print(np.max(file_x[np.where(file_z==np.max(file_z))])) + # print(np.max(file_y[np.where(file_z==np.max(file_z))])) + + #S = np.load(pathtocibseq) + #ux = S['x'] + #uy = S['y'] + #uz = S['z'] + #ux = ux.transpose((0,2,1,3)) + #uy = uy.transpose((0,2,1,3)) + #uz = uz.transpose((0,2,1,3)) + + vv_x.vector()[:] = file_x[mx] + vv_y.vector()[:] = file_y[my] + vv_z.vector()[:] = file_z[mz] + + assign(v.sub(0), vv_x) + assign(v.sub(1), vv_y) + assign(v.sub(2), vv_z) + xdmf_v.write(v, ti) + # LagrangeInterpolator.interpolate(vv_x,v1_x) + # LagrangeInterpolator.interpolate(vv_y,v1_y) + # LagrangeInterpolator.interpolate(vv_z,v1_z) + + xdmf_v.close() + +def SqtoH5(BOX, MESH, Sqx, Sqy, Sqz, output_path, uname): + + xdmf_u = XDMFFile(output_path+uname+'.xdmf') + Xt = BOX['nodes'] + SqXt = BOX['seq'] + P1 = BOX['FEM'] + V = MESH['FEM'] + [Lx, Ly, Lz, Lt] = Sqx.shape + + VX = V.sub(0).collapse() + VY = V.sub(1).collapse() + VZ = V.sub(2).collapse() + + vv_x = Function(VX) + vv_y = Function(VY) + vv_z = Function(VZ) + + m = dof_to_vertex_map(P1) + + if rank == 0: + print('{SQtoH5} total number of timesteps: ' + str(Lt)) + + v = Function(V) + v.rename('velocity', uname) + dt = (Lt-1) + te = 0 + + for t in range(Lt): + + if rank == 0: + print('timestep number', t) + v1_x = Function(P1) + v1_y = Function(P1) + v1_z = Function(P1) + + values_x = np.zeros(v1_x.vector().get_local().shape) + values_y = np.zeros(v1_y.vector().get_local().shape) + values_z = np.zeros(v1_z.vector().get_local().shape) + + S0x = Sqx[:, :, :, t] + S0y = Sqy[:, :, :, t] + S0z = Sqz[:, :, :, t] + for k in range(Xt.shape[0]): + values_x[k] = S0x[SqXt[k, 0], SqXt[k, 1], SqXt[k, 2]] + values_y[k] = S0y[SqXt[k, 0], SqXt[k, 1], SqXt[k, 2]] + values_z[k] = S0z[SqXt[k, 0], SqXt[k, 1], SqXt[k, 2]] + + v1_x.vector()[:] = values_x + v1_y.vector()[:] = values_y + v1_z.vector()[:] = values_z + + LagrangeInterpolator.interpolate(vv_x, v1_x) + LagrangeInterpolator.interpolate(vv_y, v1_y) + LagrangeInterpolator.interpolate(vv_z, v1_z) + + assign(v.sub(0), vv_x) + assign(v.sub(1), vv_y) + assign(v.sub(2), vv_z) + + xdmf_u.write(v, te) + te = te+dt + +def ESTIMpressure(MESH, outpath, checkpoint_path, filename, options): + + #from dolfin import HDF5File + V = MESH['FEM'] + W = MESH['FEM'].sub(1).collapse() + # Checkpoints folders + unsort_indexes = os.listdir(checkpoint_path) + indexes = [int(x) for x in unsort_indexes] + indexes.sort() + + from pathlib import Path + import pickle + + # Create the Spheres + if options['Estim_Pressure']['method'] == 'spheres': + import mshr + Npts0 = options['Estim_Pressure']['spheres'][0]['Npts'] + Npts1 = options['Estim_Pressure']['spheres'][1]['Npts'] + center0 = options['Estim_Pressure']['spheres'][0]['center'] + center1 = options['Estim_Pressure']['spheres'][1]['center'] + radius0 = options['Estim_Pressure']['spheres'][0]['radius'] + radius1 = options['Estim_Pressure']['spheres'][1]['radius'] + x0 = Point(np.array(center0, dtype=float)) + x1 = Point(np.array(center1, dtype=float)) + sphere0 = mshr.Sphere(x0, radius0) + sphere1 = mshr.Sphere(x1, radius1) + mesh_s1 = mshr.generate_mesh(sphere0, Npts0) + mesh_s2 = mshr.generate_mesh(sphere1, Npts1) + + VS1 = FunctionSpace(mesh_s1, FiniteElement('P', mesh_s1.ufl_cell(), 1)) + VS2 = FunctionSpace(mesh_s2, FiniteElement('P', mesh_s2.ufl_cell(), 1)) + s1 = Function(VS1) + s2 = Function(VS2) + p = Function(W) + + one_mesh = interpolate(Constant(1), W) + LagrangeInterpolator.interpolate(s1, one_mesh) + LagrangeInterpolator.interpolate(s2, one_mesh) + vol1 = assemble(s1*dx) + vol2 = assemble(s1*dx) + + dt = options['Estim_Pressure']['dt'] + p_drop_lst = [] + time_ = [] + + for k in range(0, len(indexes)): + path = checkpoint_path + str(indexes[k]) + '/'+filename+'.h5' + hdf = HDF5File(MESH['mesh'].mpi_comm(), path, 'r') + hdf.read(p, 'p/vector_0') + hdf.close() + + LagrangeInterpolator.interpolate(s1, p) + LagrangeInterpolator.interpolate(s2, p) + + P1 = assemble(s1*dx)/vol1 + P2 = assemble(s2*dx)/vol2 + + p_drop_lst.append(P2-P1) + time_.append(k*dt) + if rank == 0: + print('Pressure drop :', P2-P1) + + # Saving the Result + write_path = Path(outpath) + write_path.mkdir(exist_ok=True) + methods = filename[2:] + data = { + 'pdrop': np.array(p_drop_lst), + 'time': np.array(time_) + } + fpath = write_path.joinpath('pdrop_' + methods + '.dat') + pickle.dump(data, fpath.open('wb')) + +def OUTLETwind(MESH, output_path, checkpoint_path, filename, bnds): + + #from dolfin import HDF5File + V = MESH['FEM'].sub(0).collapse() + W = MESH['FEM'].sub(1).collapse() + # Checkpoints folders + unsort_indexes = os.listdir(checkpoint_path) + indexes = [int(x) for x in unsort_indexes] + indexes.sort() + + QQ = {} + PP = {} + ds = Measure('ds', domain=MESH['mesh'], subdomain_data=MESH['boundaries']) + n = FacetNormal(MESH['mesh']) + ones = interpolate(Constant(1), W) + for bb in bnds: + PP[bb] = [] + QQ[bb] = [] + + for k in range(0, len(indexes)): + path_u = checkpoint_path + str(indexes[k]) + '/'+filename[0]+'.h5' + path_p = checkpoint_path + str(indexes[k]) + '/'+filename[1]+'.h5' + if indexes[k] < 10: + path_u = checkpoint_path + '0' + \ + str(indexes[k]) + '/'+filename[0]+'.h5' + path_p = checkpoint_path + '0' + \ + str(indexes[k]) + '/'+filename[1]+'.h5' + + u = Function(V) + p = Function(W) + #comm = MPI.COMM_WORLD + hdf_u = HDF5File(MESH['mesh'].mpi_comm(), path_u, 'r') + hdf_u.read(u, 'u/vector_0') + hdf_u.close() + hdf_p = HDF5File(MESH['mesh'].mpi_comm(), path_p, 'r') + hdf_p.read(p, 'p/vector_0') + hdf_p.close() + + print('Computing flows and pressures at timestep number ' + str(k)) + for bb in bnds: + if bb == 2: + QQ[bb].append(-assemble(dot(u, n)*ds(bb))) + else: + QQ[bb].append(assemble(dot(u, n)*ds(bb))) + + PP[bb].append(assemble(p*ds(bb))/1333.22387415 / + assemble(ones*ds(bb))) + + print('saving the figure at' + output_path) + from matplotlib import pyplot as plt + from matplotlib import rc + rc('text', usetex=True) + fig = plt.figure(figsize=(12, 5), dpi=100) + t = np.linspace(0, len(indexes), len(indexes)) + plt.subplot(1, 2, 2) + for bb in bnds: + plt.plot(t, QQ[bb], linewidth=1.2, linestyle='-', + label='$ Outlet: '+str(bb)+'$') + plt.xlabel(r'$frames $', fontsize=20) + plt.ylabel(r'$ Q $', fontsize=20) + plt.xlim([0, 1.05*max(t)]) + plt.legend(fontsize=14) + + plt.subplot(1, 2, 1) + for bb in bnds: + plt.plot(t, PP[bb], linewidth=1.2, linestyle='-', + label='$ Outlet: '+str(bb)+'$') + plt.xlabel(r'$frames $', fontsize=20) + plt.ylabel(r'$ P \ \ mmHg$', fontsize=20) + plt.xlim([0, 1.05*max(t)]) + plt.legend(fontsize=14) + + fig.savefig(output_path + 'Outlet_Windkessel', dpi=500) + +def ROUTINE(options): + + if 'Outlet_Wind' in options: + if options['Outlet_Wind']['apply']: + if rank == 0: + print('--- Outlet Windkessel ---') + + mesh_path = options['Outlet_Wind']['mesh_path'] + out_path = options['Outlet_Wind']['out_path'] + filename = options['Outlet_Wind']['filename'] + checkpoint = options['Outlet_Wind']['checkpoint'] + 'checkpoint/' + bnds = options['Outlet_Wind']['bnds'] + MESH = LOADmesh(mesh_path) + OUTLETwind(MESH, out_path, checkpoint, filename, bnds) + + if 'Corrector' in options: + if options['Corrector']['apply']: + if rank == 0: + print('Applying Corrector') + + MESH = LOADmesh(options['Corrector']['mesh_path']) + u_path = options['Corrector']['u_path'] + 'checkpoint/' + w_path = options['Corrector']['w_path'] + 'checkpoint/' + wname = options['Corrector']['wname'] + uname = options['Corrector']['uname'] + mode = options['Corrector']['mode'] + outpath = options['Corrector']['outpath'] + + ERRORmap(MESH, mode, outpath, u_path, + w_path, uname, wname, options) + + if 'Velocity' in options: + if options['Velocity']['apply']: + if rank == 0: + print('--- Reading Velocity ---') + + MESH = LOADmesh(options['Velocity']['mesh_path']) + filename = options['Velocity']['filename'] + checkpoint_path = options['Velocity']['checkpoint'] + 'checkpoint/' + outpath = options['Velocity']['checkpoint'] + WORKcheck(MESH, 'u', outpath, checkpoint_path, + filename, filename, options) + + if 'Vel_from_check' in options: + if options['Vel_from_check']['apply']: + if rank == 0: + print('Applying Velocity--MAP from sequence') + + [Sqx, Sqy, Sqz] = LOADsequences(options['Velocity']['pathtoseq']) + BOX = LOADmesh('cib') + AORTA = LOADmesh(pathtomesh) + SqtoH5(BOX, AORTA, Sqx, Sqy, Sqz, output_path, uname) + + if 'W_map' in options: + if options['W_map']['apply']: + if rank == 0: + print('Applying W--MAP') + MESH = LOADmesh(options['mesh_path']) + filename = options['W_map']['filename'] + outname = options['W_map']['out_name'] + mode = 'w' + WORKcheck(MESH, mode, output_path, checkpoint_path, + filename, outname, options) + + if 'GradW_map' in options: + if options['GradW_map']['apply']: + if rank == 0: + print('Applying Grad W--MAP') + MESH = LOADmesh(options['mesh_path']) + filename = options['GradW_map']['filename'] + outname = options['GradW_map']['out_name'] + mode = 'gradw' + WORKcheck(MESH, mode, output_path, checkpoint_path, + filename, outname, options) + + if 'Pressure' in options: + if options['Pressure']['apply']: + if rank == 0: + print('Applying Pressure-MAP') + + MESH = LOADmesh(options['mesh_path']) + filename = options['Pressure']['filename'] + outname = options['Pressure']['out_name'] + mode = 'p' + WORKcheck(MESH, mode, output_path, checkpoint_path, + filename, outname, options) + + if 'Error_P' in options: + if options['Error_P']['apply']: + if rank == 0: + print('Applying L2 error to Pressure') + + MESH = LOADmesh(options['mesh_path']) + refname = options['Error_P']['refname'] + reference_path = options['Error_P']['refpath'] + filename = options['Error_P']['filename'] + outname = options['Error_P']['out_name'] + mode = 'error_p' + ERRORmap(MESH, mode, output_path, reference_path, + checkpoint_path, refname, filename, outname, options) + + if 'Estim_Pressure' in options: + if options['Estim_Pressure']['apply']: + if rank == 0: + print('Applying Pressure Estimator') + + MESH = LOADmesh(options['mesh_path']) + filename = options['Estim_Pressure']['filename'] + outpath = options['Estim_Pressure']['outpath'] + ESTIMpressure(MESH, outpath, checkpoint_path, filename, options) + + if 'Error-curves' in options: + if options['Error-curves']['apply']: + if rank == 0: + print('--- Error curves ---' ) + + MESH = LOADmesh(options['Error-curves']['meshpath']) + ref_check = options['Error-curves']['ref_check'] + 'checkpoint/' + com_check = options['Error-curves']['com_check'] + 'checkpoint/' + outpath = options['Error-curves']['outpath'] + refname = options['Error-curves']['ref_name'] + comname = options['Error-curves']['com_name'] + ERRORmap(MESH, 'curves', outpath, ref_check, com_check, + refname, comname, options) + + if 'Temporal-Average' in options: + if options['Temporal-Average']['apply']: + if rank == 0: + print('--- Temporal Average ---') + + MESH = LOADmesh(options['Temporal-Average']['meshpath']) + ref_check = options['Temporal-Average']['original_check'] + 'checkpoint/' + out_check = options['Temporal-Average']['out_check'] + READcheckpoint(MESH,'average', out_check,ref_check,'u','u',options) + + if 'Temporal-Interpolation' in options: + if options['Temporal-Interpolation']['apply']: + if rank == 0: + print('--- Temporal Interpolation ---') + + MESH = LOADmesh(options['Temporal-Interpolation']['meshpath']) + ref_check = options['Temporal-Interpolation']['original_check'] + 'checkpoint/' + out_check = options['Temporal-Interpolation']['out_check'] + READcheckpoint(MESH,'interpolation', out_check,ref_check,'u','u',options) + + + + +if __name__ == '__main__': + + comm = MPI.COMM_WORLD + size = comm.Get_size() + rank = comm.Get_rank() + + if len(sys.argv) > 1: + if os.path.exists(sys.argv[1]): + inputfile = sys.argv[1] + if rank == 0: + print('Found input file ' + inputfile) + else: + raise Exception('Command line arg given but input file does not exist:' + ' {}'.format(sys.argv[1])) + else: + raise Exception('An input file is required as argument!') + + options = inout.read_parameters(inputfile) + ROUTINE(options) diff --git a/codes/SENSE.py b/codes/SENSE.py new file mode 100644 index 0000000..83b82f2 --- /dev/null +++ b/codes/SENSE.py @@ -0,0 +1,115 @@ +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] + + + diff --git a/codes/__pycache__/CS.cpython-36.pyc b/codes/__pycache__/CS.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c0eede00f50d427370bdc2ec230ca0d976fe68db GIT binary patch literal 15426 zcmdU0TZ|mpS*|)&-Ccd}>FK$8Z1?V(%}y@sOBRS$PQ1RYy=-P|JWdQ9dnfHaJu^Ks zeVJ1=-kILh4(#lPMP!KqAweYaus}!xBmu%jA`ej%MMC6>H|ik*fwiC|-=9t=-ukP595O(IQ6TSi_pN@*FDF{Byk$T-rh zOvohCoJ`3y(lMElS)_THlVeE7WnPXWEy#kLKsq5OlJY^5!aX*22{nDmLNq ziG;uNNZsoIp0RFfW6#v)Awye9W8CQ2($qHaLSs=j#GZK?ixOb^wKq)0_iAdffmTi% z+Qu-fMP;Jx`vm4KUo=|2Rle=|k(bx1syZL>%?)2{yzE;Wn@!)`^3B#443$RZ@6R1y zYu2mBcdNVAtzF-0$(1Qoa}xlDD42P3+RO`;#ZzyJR2IdL zr}(SL(4a9TV^4&W5{EF^NQw<&Lzb3?0*A&+f$Wwxi>;m>Usw{i?Bb{RZ_OUr!LW6W4JpjvX$J zz|a)!%Y0JNw)oMqDmPZEzFn!-HvP!TX0xgMh-z*(BoZ#NY7LKP>s#)2-M3a&Jl_Fu z*J>-?e8M*yzTIf5x=K=mqP2o$c71!JUfwBLjn;~y#Ze9wnpb(n1CSw1vR-yKma)Xk zCuI=`w*X*>BW4EQl$FP7XUwQbIf_bq>z%^`ji1;18EiR`4OR?mCk0Zhsg6jC*1Qu% z-VXCI&jg7@XnmzM4!n*9xhbmYpwz<8Cep*s1-Zzc*b_HJC*Dc$+lk)W@u9bqD2?cN z&=*>@r>V_2V-vw>df3EH+lxvQyXowKPSCr+{>n}YwH=JlUIhzijK7lx279Pe8>UVW z+!LJ)aM)cu*^I+jJ6WC7*%?Epz*2%(N~d-9w1JvQoertvo1l(w-k_4qssL3)7MT{9 zZxk)*Dt`F#CEq7w!B_-*H%?csxc}dYF85kCINiA*{HgHaxrqD<#pc__hM&_-4sBf8H0@uK7Z} ztd3Ge^Sp1~crXE-l0S`F?&AQ4a7@Qc;d{g^;x}ndT3}kUfbS#`l&wypR)yGsJ~Y=J z`#QjafmlM3EK;8giHc;C1>&+i0d|G#!uEo&Iv_L%iR!;zr`eWY}XM%Eu!Ck^tjH|%?+T0_k^ja*tA77M2g zl|g`Ixs8O*5VNgAICXMCUgy9%+1G)^xW<6PdJW<760_H1I=>=L8x6^Q8R+ZVL0?%~ z)A6wN@qyNDou+;@V6cGR5t4%ZKTW$zU|dE zt4xI|Mpcrns;X~$Wv|w3_>O9BZkBgyu9~K@c&#gL{kVrF+*Z@A&KGEeK)}Xsecrz&Nw@JN* ztwBfvAAzPG=q*@t9@{XUcWkgGwK>pQG+0#~rInRLdeKF73Ix#?CF=e3NP2fZ8p@3Z zadh;K>y;}TesnEJV~y&|BnTH-D~VNqK_6NnczzTM`$}(ZeZZ&W}=U2;}U-uB0~z%eA+xE9Fa5U=qnaYe1%#-d5?z4!s^lRXGdxHJHz`-6ooaQ-H(QQ zKr{-KDPvtaAE3GsS`XhQt2kJFhjyH>J&YyeLv%}YZfn?FEdD7)ZE3Dru&nGi1vmi~ z)Zh+D@DrQ`DDNRGb`n@?fc_(_Za>rOd4L{hhr?MW23ra7u~8h)KiQpsP&z;*BdgFa zM<4yQNcHhS4y9pF)K+htmP~hh8tCIdehkO!^xh5Tm?3=7N57|`K7x9dgpwcVgFKpj zd%=4Ht6WA_?Fa5j*xrhLz|I6^kT@uVlo}jYm^Zl$d&eA>TV!tPD`j}15$WwhwG!vu z|6hF673AJ2n2$4Gs^{sQO9UxbEmAqwbojH8#GES}sXB16n>|lGaZ_=R;wB47lF3 zig@S=o3CSnG%X1>hIMUA8&-CNT)9w1MPWUk&=5B_E!eb9C*F9nS7xDXk;`C-qbz|^ z$AcK!Gha15SkY_`2)2YV;dKGxbRaNNG7jrEE+gcoVL39r7SS8*?^o}cJO2)s4Q}-X z*sQm{13MT&7xeZQUR)-0c2Afj91^fI4Vje0_6&8FSOqqJ5{sYHxpfn^aSm@2S*_qQbcq^wT^%S|o!CQKQ$?kA4N`^^&7-O8}(NB0| zdIC>VAk8CQULQgK*bl7Hq&}i2LCjP4%&l+0Z_4QcMv)Ikg?BK<=|cu;!n^=vI7P5MX7J3u`GYWffR3H7}sRBM7DLJCqK3yb08TJrmbTI?8L0%&21oUyh z>R{EF?x+W*kPIkb78Gy@=^WC-NRJ>rinNIIF{Do*J%;p2r0+sHkMu{6VyvzIdPIt` zw*KYqDW<=tr;U4pC`YFtMBm+ht9TyTK~-J1DvQr=H!9@aJ)KAt@j0tj-Df#RPcK}* za{XD#6yxP0oUqnzv0nC6ZKwEh&08yaYt`b)_U2~MEt9s9#i!nXq1aT#XD-YaIL&mc4SX#cM%x)FQoIu2iaUIN84}2Hp!-y-!BoeGbu)IeMSNKI|fq%4{FHFw}an z<`z|TYrE=tRXJ~}Mbu$~wmtU>Ms)tl!qsaRmzFMGC@x)GTzX;gQm5z@KUiFB7eDq4 zikEH`ui^0(RqYhH;1#dhIS#PWp^&YDC+1as3(xmS70ipkSSFu}RdyG_<0C~51m}A- zy46_A@5A;G@Z34y2i)4AKfkZ;a7RNe^u`l(Zw2mTrt``IjY{U&tv0thlqZ$zkB%JaI-C$Fn zEeqDeL0Q9(uE4!5d-Fx#CYn?qr1zqYS_2-wA8FiH)m1;TS-&mIzNl~e7VH4uQcc9w zD@_EDLAvO`lGTyhx<#CkQT+&x3d|1%mzLfOG9f zxz-8as?}H7?C{NVe#8Z(BVJwKRx7@}y+NbmxCAD^W3<$o>zil&7{9%IV$>>e&Mz%o zyngx0g}=r4+|L6Taf(0i*P^gX|{#XM$ii2!RsSQJ@ct^<<{G0#KS$7Ku}+EmkCLdIcznXn9! zG7)NFYn`Hd2WjCP1tp;8#tv%sX*$8=N| zfP*a-SWBHl{dZYo&&iaYlWAz+4AQ{1n+t8bxzM(o3vIhOw(Vw7k2E_X*W7l5drIrM z&{~VJjW-7y&%vQcVB;Nzjpu|G-_6bueF&kGyq?xGJsU5kr`X0j%B_tvEa;;c^&DFu zQ{IH0!qW_FyrMU$i|9YXHr})@>S~$!a8!5)^PgoKFVDCG)&y^^ z;ms*M0UHl>J5$KxI0UZffK?vkHE00V9&CfHf5JPUMmW@IimUSx$>ARd9jEi^-0E_B2;E;AQsq9BkVNS729_U6ol?wD{9=TF> zsoHRBUhPiJ+g)BLw?=fQl2pA)V4VPk-PIZacKs=`%NkVGC`UmuMQ3Gdg#dZytV8D? zQyY|Lof*5fOg7L(wMnQtfd+vlffj)+0*Zh~z$HM^yc8wPdw!|p(4eaeXRpFEa@7u% z{}O>+0&N1X5YPlV1nv?b2VH%Fz%LN^MFOu9*dy>7f!7Iql0do#_&7GxRgS^fZ(*lh z8o%N6R3sD|<&WWOo3l`0vkdca?F-@CkwzeiSc;wel03i|7*xg*p$eyrxMA_nkomSCBaPPIKtZBZ=sLVITrjA`!JKhB!&e46fjY! zw5T3~;LEb$hiHWhH_!uA*o=(p8JU0}Pa;hrO(V@9%_7Yq9YY#8_cNgamMM?xheU4j8GlVK4QO|;(6(yb^ z)H{a}7&zP${1f`Ho`B$=gp2+LL@^HgAo$0^Q59J5PqE<7GVXvi!JBQo2}KOSkGh=# z@(}5x`$-XBx+kI2aMNbn|N5ivrjcjpA^NXEuZ~$;++1GoZo(Q!=a7pCHN8XPO$a`{QM}_($O7SCoDPD^3qW|zRTy4{M zSY-eIN$WySTDPj@4R_b|nw!-xlFX*Cu#xD=Y&!#)ToBXdQ;#m0;moK{p;cd;xKttI zf9iqs1PMROFmg_K3a8DS+3q;U#oV;Y7w^0@y5{=?lQYNBnw@6vlN zkygbAH&86r-hKpkkl^o$Rt<4=v4GRAg%iI0(Tj`ceFv^!gQENJd2x-YzE7F8*2->m zxzdC?Tz0*GqlF<=LUCvZKlPi)_ohNuRQmo@ESL)Xso-`8Phg#*rgV>h6b$9*HV5Ys zU8W-^x{NjWoWL{U&A8%2M@p7@gWf~LI@w9V3q!08zbI}*;1Keq6pW2P~q_TnApx&=W;Xo%Mtq zhvGnu6+!+IaEMXMAlYA;aQX z?WDV_i#dg3ef!p@A2OFmY4ZUirc;E>{*@z-7c(83B9j2h8nvO9+)S!p>0c#TU zuy3^v?BM~m26`AePz_dn>mEnp10Kp_{bTCG%tJQw(8Sww5oSi*g$O@5$^zekqhMZG zJFOm1S+{NzPa(R01hogaN>9L_-p5xVHV-u$au#C-cq@GFa#tbXEuS@gS8Ll!F~<& zA8=w+z0{v0+GI`)Rv&G^bbKfMjB?{pKRs#nsI8CkjZ{J=hkxOTMeK%Yar+pmZCowfDPHy}Oe9wLu^&6Z=;Jl6) z`neOnxPGw|y?XiV(!~>DimQ6pE?+sp@Z><8fI|fA-@li7B4egxUr=k!QiR~CQv6O? z1uglpdQ)z1Zo5Hn;XPD;#Mz(dUfWwJuQsY)t<8r+-y<{WuMoZ!D9MWS5 zTHADq7EyqVc+PwZ0r5q%0eIcKE^eDERt_QYf_Vf%^C)gJOyjMbb=iCxHS*?V@e3j$ zUJ@_i25s9`Z=sJ0S&;O};s>KEuq1tqf$k_EV23+Bod^!zzojF5=>9dj1V9I}>RHc} zHm<%#_vrq#iQ`t7S)AhLO!#&b!Mvayg!P~T=mIQmdD8_?)W_{_yiI1CDRHRJ7>6+l zc)4`LI(QeYKounK#_l?I<98Fd>Pt6^Xmk&1Ke4ZUgsUIYerlk7x})^q_IdsYcfS|o zPL1@`ExU{|n2keycFQEnGF-NQmN4n~xSOuznou3M8Avt5@#HXP7!KW4mw6a?xQ#By zbtc>cilEr^M1~Q3@4}n5Y1~cTP2Ejz6>h++VjRzhog;3)g@OP|BEQs;kztfYuisZTJ3hWTU?}qXNx%WG;!4(w}jgB zPCo_-!Qm-p4?gl?KPB*na_FkshD*~uRi4lK*3#Av0sK{EX{+tWntVd&!aYLWR@qw% z;*q9ObOlh|11LonPApekBqx#hQM3@IyJ3nxTt9~4(m+QAM;iYQsVY8-#=K7>DCg3} zCqtxgk%{i}IyeiXyS#L6Rv;nLf3^xFRz#6b(&)Bt7m9*KcYWvZo5Y10wAK?1bRk~D zFdI?zfv^mxJS4(9Q7D*CX`2_nD{(7qENJ?CVpDc=O$8Gp;G@+!v||j3UWGm3xvY5~|?{sVqHGmPH$xp1`Gl znM7FNI-taq%#y(68re`J2Q}~nn#G@if*Md|2?*slM00xUIgKl`Jif2t?`D`8C^m;2 z=7iiBa^ib(}{6YdlazJXQ+p=IGxU;Yf0K$L{90p2PX*7~Rm@ zdM;EG`H;SuM8ATq4$icGnR3``<6&xpFM~c!GOValwo#@E$ntNyIoAXi)ja#L@3CY z-4msL{v_l-$$caw_K}d(SAR}p8Zi~ehnd!0Ybx*4#Ixs68FC-@B*;*tI}woo;9Hn| z_y!W4Wje`q3O@EZx-0FWE!1D56$q|32a>~lnWVKFtQPt*6maYL+ literal 0 HcmV?d00001 diff --git a/codes/__pycache__/Graphics.cpython-36.pyc b/codes/__pycache__/Graphics.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d0cf857bfc5254147e0ff22b58e628c6daf3b463 GIT binary patch literal 36990 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 literal 0 HcmV?d00001 diff --git a/codes/__pycache__/MRI.cpython-36.pyc b/codes/__pycache__/MRI.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eaa8bcce864f81de0ceec8ef3fbb1bdac8387391 GIT binary patch literal 49504 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 PweVErsV7hKBJ6(yd^0aH literal 0 HcmV?d00001 diff --git a/codes/__pycache__/SENSE.cpython-36.pyc b/codes/__pycache__/SENSE.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..ff2532028d06ba3eb1bb91d163128f850cfd3109 GIT binary patch literal 3377 zcmcguTaO$^6|Snj&UJ6&^x2c*+ISt=v}`Ty>7Lmc&&}0s zXJ%C`A;u9eM9M1?kGw=kh#x}!Ks_PxWQivp0Y!YLW_P{oIInc8PMtcZs=BJ{`|6yx zE0y9OemQvfpE<_bbZWmr&2g<+y@+A?ACmUVVY@vE4e?Zm%6cd+2YkFxc%gb|14@U0Zom`UYwKl($7*Pz5a8*_E`w7xdd+kk+I7zSU z-Pql`@x#$X&+TD?PS$zW$tL@aXjH+dv<$&Sk#F!CU*Ri4*3fR+WW{q1rGR37b`Sef zyvrWgv!9oH8Se^ZXBK|4Q)5%ET;;Xx%#OvUBKP5Sx~_s97-64?BWbm)RhAcyyyCUq z;`qzVQ_hrcvxoo6OXGi{Wt-OD^D+*otV*ZnY}uHxq6%bh3Fy_CuAKACwC9xd+A;I0 zcrs>Trk{*iR28*QV`^SiYYc#xGp)s0Yn|mw@Glzwobgvp%k)|Spz@lkDgUcq-DGNM zW~VQm-Nhz*@|%0?iM+>@4^Y{=k`4k4aN=w-N({v6zAV8gT?p+QCUTf+t24;7*Btgo zy<{xuz$DQ`J2D!yllnO=_O5EtK-t?sy&>t;C7r*lQa`bqY2MIQ+P_L-L-VfYkG1Gw zL_`IndMJ;eKZ5st&9@BbW@3rvC>fmX%cMCRoQEO(76cPjevw|(RldT?Z2m|FJOJJ< zS@H+yb%M7GXq@2f%l{+ZVmB|vPF?~k3Dv$TsZtx*obtSkcA*QLK(Bnp$E~b1L*{4v z;r+Y{%WYT;I$?P~p94PURQ2r10+aK=B2m(k{PvvRz3EpcFUU2TXq^OMRDOfRSr*BQWP5`|K;oMap__KvebC3c zopwSGVxPW6)R5mMaf!rtNPL&X_efkOQHRicPxFs7kHSI(V$pKqu<-0y)%@A3BrKmI z;l`VoBHe&s))5Q2jkm_jVv#SNVdFBt41U4``n)Gw%p^L&tF;QTdSjkKj zK**&?&|$fY0^T6(TFP!)Q~p3GFXlLVFBY3D6Bz|eE4J2wM4;3k|21$DQmT$PSXA^|aRu(ul6_IJo@w zb}*E|JKOajo(!UXry2EvILe}v8Sl)dqZw&*)NCfbL`GR>I0#x%GaE|N)zHPTH?bgdJck!QN;`vguyy(jKQLz)+zEah9Ii&AQEx(B5aWlzIG`v$ z93+G6RoCR}U577Sbz9rG;~r~gBq?jK(oC8^S1%wlK;GFv-q|?R-f%>CO3hL=m!aJl z@28LxBMjHFlWNrO8AY>7~!-QK&waRUsSj))zH_W;8Jgjk%9Q zadQjnnxxw8k2>$bWuc=kUcc37?BBa}=jJw{so&TBhe@_?E@|6H)27YI8yH|RS(9EE u(3(w}Po7#hCC<{MFaBnK7(eYLKf(3JQVJkGkVVC%MZ12{U-B>bYySgmjRPD2 literal 0 HcmV?d00001 diff --git a/codes/__pycache__/ktBLAST.cpython-36.pyc b/codes/__pycache__/ktBLAST.cpython-36.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7cba0338d39954119891b283ebd0289f82ac14df GIT binary patch literal 19395 zcmdUXdvILWdEegG?%f9#3t;gi2(D;IBJ|(`f z*(JF^?y9yRc`~h~a#T+rs@uA0o5rc*KH{d1lRA%f(l$-oj63a2Zf81bGge~P40)T^EWFJXbJf0P8%(oSoYnZXxDhMGmlD_9lDm}Lj$KRPoyI%k*`D)y z>{^%iq!;%RuN&90p6ewM)9t0aG~PKc<8|TP<7K^WynDTz*MoPT*X#A+o%ixyKi>V` zfH#QufH&j~<2~q&c>C}k@P zp$B8$5pTkK488;2HM7;S83!U*D(#f5Tl1wLzf_QG6}@%Y<^hyJs8 zD!-3O@?*Z?n+sMw>D#{J$Kgx))>7YJ(r~OP{%+D;C+eW=>M@-gB*1Kz8 zs#<>65~g)HwrxzsuD?^yRc+*T{G4ZPvt*ABBQDOkeaIK4^oIHDZPPQCP4#)d+cQ2E zt9SbreC9mr^pmW4Fy?omEMiW^kk;!NVVV)8Ax6@AJSR+ZqBO*ujBUJlHCB7Oqqm=` z=W4Yu4t2>0=IecI&F^D9=vVBXp)NLK{FL9{fNqK8xjihh9T)M`#x{U+E{F>{9P|zAF6#G z>o_1Qc&|R((X-*GXF;b_xEk|^?irPD`vXGX1G2W^ z><@E|qfv`L>_xcdBgpOg{r{6$dG~H$ojrT@i!pTsWBI{DM{cdHmX2(eHcLllZcJag zaAa=HD^-pxSI<0u`tp^->zhIMxjQAbd3t5BSSfkOrzW!~SGfcyW~L1OdhxT(ypc0T z@VMrvF=`YL&Le)*7%&c5LvUUB+1421@UuT-n5J!Hjn5b&9OJ zkBdk6@hFx7J6rSPRK$DCa3NJw*jB^$)gi~FL<_{ zk1gY=_X$1rdB!riJNZ-+^o#o65Uv6q)i14ObZc)2x2X?+_on;-AVq`EeyTo*{m|HP zws6g{));WiFdZYo&LPhM*Kj1~v#l|bGvrr@kB2$q%Z~bPYgqD0D)8XD*g;``>O-Cb zo-t4#sa-=ahlGpFpnr*$R+{xjy%sLyEL&KKdzgo`KjIJi!{D%nmw3~vkNCr~--oeZ z@3FPZvD%kWe-^Uq6fQyt8UQ*%Pkt(%FDtsNOiE5@<9{9shm_H0jpCdGK1o_^R`H6Z3ejfEf{9z3t zZ$E(CUH+JVKzMrsynPI_{~l;%Y$;pKkhgm=@b}z|aO%LW6jw{+=U~94h41{#SI6G? zAAfjCb9A!r2}6;oD2EOqpu_n<+`n6qNvSlQ44lBM%qc=i;DX8DSzEaS7%1MX00xS+ zz`1*?q)MuXxx1Jt?v++b)siABRlRij;7k-$p8kG118@R!YE}&~G)!lN4uw=T3MYtP zp1pML^px7qm@zsB=oH`t*3|4wU{4os*8=M@0b=?xfC1gPKxejCQG=3g_S|XpD1G*f zfXQOn3*v|@m+q=@#H+{Y9HKKp=P(@thjxy_7i8P<;XL9hH{mqkAq$wufzcNL0x3LM zz`_9Fq1PCaCufXWDZ@5wD{DLf(8yZ0MerDHz=w_e8a@Cd@-yGoaKX0bxSIUqL~(%y zF79A4`~(>=7|*w{^^66x?t*35ctc?JO|a>dZ#IPa+B;RlPYb(wtKL=nIfOu35Z3*A z78|w8&&sB9{j4yWl#an>41HP*R`;4=Ke=~aod(uB)tMhmCaQa5>S}D`qhK)Rk_GWM z9Wj`0#MlkNSKuy(5q5hC^atSPxhG?_|6Vn)v84=I%Jo0MIKa|`p=h-M>H|k5W6<%M zp%5T-e3%29Uwkc_-%uIENj^!1uOro|0x}ypzzi6Y_JkP#q^QndZ89>JC=CoCDg_3h zl_QgCk>4W>zy<@z0W30L0J)_^)gc4GN^91lI9FA-nv{|P&S0ZmGRin0q_>*h=F0aW zU&ikvIHQkwgu47Z06ZQ7ct2vY6n+K32N1FWb4>srgqna*Lu}9h9x|eoW<)zU4%E(d zRVsQBPuh#q2t%3(Sq%9_lh0@#(#|#lORe1vobv6}>SW-a74~y^R{bOkew5C~=zJW` z#83-^d5W=3<`VH0b({%JrgD;^E92)bk5Krr|IMwnO2_hS!Ad@ z4Tl^SYh=w)GlwT{j++!Qkpiy4{XcIUgs_;hQ{W{TJPod*o<|*X6!7^+UJ&tv zpGUxt$!<65CLjgk-%^aKAn3_r7}Tlh&Bk6sXfOskacZ}qnmazIOt`^I^*BGaz#t%iU0z-E^ul$p?#%g8_44NGYN@Ig=YAb! zDg>h#CX@_2gGqk^zEM+MM(i9FA^wr!@)1Tmh3T%wmJF~~bK9)j@N;Udsx4FN_=eam zZq?3U8o{*4%D^(rZ3|54i8>~;F-3Y(DKA1=52vjWhbj6vrU()?Y#{%-_TnyeJzckI zPet*N9m6)p>v6W>#~XF&`kP_Y{dq9j*QNfrFr}w!D^X3&-oA(yW~2B-)WTEsI3&2n z=$b8$)nT1L%Lx!lI4bQI>&5`u{1KjSp&(z+SGw%V`hd^e%5H z5;SN*1dnd`Mf%XBF~cC)#e^Fer}Z|bprAzwr&28{sEZelossPu7^-tqI-i)CI(O+` zp-6?|M9j<>Iorj4d%~nUWE{f&)Cl~DrTz?Z%mHQPk1|lS*IofhaCeb=sxQE2z+lE* zMjSJ-v=&g#+O|L}f@4cS2akN+sd?2nmdyZZV5cE9K?6^;R9bmTRAGYz*M=hI8z4Cs zlL}=D8peXebxk16S6 zxt<1pX!Q8yojvx`TzH_&hwd|LK(D_CLiwidxd^-Q8KDG?F(ipnJ z5x6Uh<;r?-uB7QDB9*|JpRa1c)v4ZIE^WfvfS8GldI6OpwKyjXC9vk!U_n?c!#Xkj zjHakK3=;Eew}bdyNR2?Cgbq&zmRDNW5YfSIx}I5Ffz-QLUU+tK;nuroq4F3Uuze6# zuaN`O9|FID=x5qi2K*<7SO9_874pVGOD!UIM0A9~hz}j5z}FzUAGH%51URsEa3m8% zMxt}T#PI_OI#I|#C|-?wHbf{8XkM1B_R(qry_P(tN%y%hh zY}|wuRiT_F5SfXn1KxDfL!^Of=$2yb#vr zF(YrG7A;c01_663nxC?sAHOTyq^Jek@B_>cO2~YP6=(N3>S~!K-IK3~*8U5aEgL*H zskc#M^H6e#5I1nbQL(l%4N8`w3kSPj4ri;(G@GI@7kR5jzaH<@P7!&Nug zfHBv}$uk$4O-}zQ@>D4PHTD^IR1TulIQAQN*eEP?+-*?3n1c5t#V@4v8e_(!rS76^ zwCl)i;&=r8e+M2xf1rLSOqsPiuu3Bwop*Sk!Pt@mAwJwWA$5p_4Gh}U;bttX?aYrI z)R{tNx-%Agu7DK{b3;l%JJ@TaBvWc~k!A_R=x|cP4!8jnLC`_GfxVimh76UwMH_}o zm5Ee~5H7lZ#6#69$QLBZH!HUm=do<`PO3l4XtxnNVQZFZSHMY?2+LIQJ6Fzn?#h)% zK!=qa5@Sg&(^2CD^xqtQs*bowz9sgur?L>^@Ngk0e8IHFO>RgSha(7E4ExZOAYlq6 zgXC){f|rca(xc-@)F$IiO`X!u4lZtAKp%gCeIyygT=dLTufo?xB9S!kE>hSNl0-xz zZ*`D}zdMOUBw_Dd_-5Mf;$97?UobINPW&wL)Btms5G&=(@S8BISP(w5d03y= zK2SEx)76s@S{W;0eeRlw!upIh%n8i2U z%%x2?F|qq!Y_z(gF3AfXax6{YDpW18+wnrIT1Lk#AIwc9ukkLC!*u4dg_GrbOb)X(*j zdUkIkJOc)@KsN+UWhkqO36Q?9cA5f1T7yZhGY`_FM3g5N=Fy{V)FYuNPtVRgNNdm2 z3u9O}TI*VX3kNy+l?aV`WP<7wbcE4^nZ?ug<9*sFLt#zbqC@kH81Y3*56qi419NUJFpI??zP<(#u>zqJMjIRn zpVjs=vDV3%01|Mdz~nMo6aO6ioq|MWp;W!0>pC&@5}ED_8jXoymxV1Y1C{HL7V=Cg zT{!`bULy}%8*TH=cM34Vp9>3q0Yc-rA-^nZ7?m1CZIjR_Oh*Od5y_+8LVI%-Tg4yc zVV<@KYrls6P+fW1hR$u*9k6yvE@0-=))(whPDtR&hKnazyBS`XajEemACxuN2rkxB zwUc2=Qc|G2Ny>OV4HYi|i+5UMx_0Mn5OLCjGFMM-ybO`i6~9aS8*KhIl`z!nLjl17 zF9gs;YiaHGQ}bFH*&_|o2+Kk_{4ixV-a)V0N;bq=wkns7;y6r}dsmR@cnOJZF&t;u z&p^gYMB=Q_Cxt|9I0~h`NF)(KHaf&oO_8>nMMN6>bM#Rb5vgRNOUs2~SNarV#oX9V z*`V6XY7U7s7;I`|fmx|&i*$!D*>zcL;2!c+LgomR{~;(R8JrG5 zq_IS#G1c416VVn&5XqaP4cf9aZ8a$i>aVu<#z9kw+C?hEu(9oH3m%tcux(otgLC}?LLv;!M4YVsh0Xxa&_P9fDKwI!%wi)zM3^zwo8 zZ)~CUFn2^9T5V>_NdS~qb~F{c5~i|~@>6ZfPDC9$WYrHq7+aY17Q#rk5QfjBCSeG- z`-_YtQE1DM=srKmUxkoC2PBD5IfAl;bgdiOp)MG5`oO-citB0;RZN(Hdvon}*(<6|ZB`{C z)2B3+qK>aEXsO20@1!?j!A^Dz5074tcZ^Xzha&%lV-vX-;qhO&nXKNuGYkH%H8Tw&?q*K%+g{)SA<<2Kmbar9w}KHSw2&US=()YzII zGE7?-@=9B{wvZN%vMeCZt| z-XE)k*v&o*i3T@LH7uf+=5`#A*Bmh! z3x3GADCxqwISfE_MXpQaA-Ur24MKx}8|Wzx%;&IXO8mZiW^DkY9r5?cZ4~o*ygpj( z5;@aUUqS7OD(c)uSsuyvY! zG}MpbC_FA&!XH`*%D^sVX+wV zSmF`H@R+z6^C)^c4zr5Ti)aPo;3BP|=*VFhx6B|FKZ5JgVLC*Rhy4T6hdk3T3y07` zzyApK@C1B3ZXWa>^(S~Y82+Kw@V=OT2qhl#AJg@D`VjJ=AE!T{EsK{6;7*DQ>sfW! ze+agC;TVA z1v&iK>Nzo0c<#y>URHdnP`HHntyG~{_6mh9_ zw#B;Fl!C;tXTyS5))Rgpph8@*Z%tV&g>Pcy?J9XWWX-BhkL2KHLH zR0&*fvA8e~J8+P!qEKahtx|%`r(7;6l)t?y#t?0PI}+FzuDo!isU)=EX{18Hnp`ba zZmr>5FJ8rcB6OjQCUN^`69+kp3IsF+xbZ8`!CDOE;uHGq=vPW!H)hUVJsKn6HZe^%B!X`D3AK(<^mN1(y*_CdzX*g4!U z$WueI-9XuS>6sRIe5e}6AXZ@@Gl z9a5*0hv7*~S%mhu=V-H*Ks#=#U^@}o8!!)DAcFZ;Sm%|wR#<1a71kMUg>{BoVV&XL z+V6plY8d~z+@9GB#`_54UKcN6+`F7Wc^{yB zHz7e<-uNn@{1uEvpWt2s3(Enr(*oRS0GdN6@9Z%cc=o}$1hR3BU>C^FYtRO})c2G| z0M)pNFOVHVw}&gjem@~wVA?^CG)xZxrqL^bX?$%H!8GAK={56>FciUgGaupnF^sqg z=Och~Ts9Tq;cdVQ5srkTdf@}6p*8h8g}G(2<=*aL4*TRD`7u} zk#Ih>aDW?MweKTFM1$+!ff&&1_eDa$K_~&vwi^loFd~LRfD=MK>!c9ShuPOc0An7- zNXBu1t09udwrwJThy{-{g#>~90@{?1WSH&9&tO*%YwYk_rMhLST;xo@Vvz~JAe^Ye864xPVChi76T znybG@zgSI<)7MmvBQRILz=XdKCx~w~!Cd_!qrXV!m+1ThI$xsm%XIz`oqtS6H0oU- zI|BGn}OiK zXQHi{w+;#xyMn&1eGqp8d1^}gk;dqw$W4qsX&th1g6A5g1*3ltJqXOB=jTW){39*W zFE~x@AIdgw?eXI~e3}P84w&-c!4$-EIg;9jnOfqYa5v9bx9lg+KYo4zb>I(I`1Bzw zz6L5Utl+z$^+gzs{|b^|A~+h@FP@t@8@QFZVwt!9AYm3&akXb~-4=hc z;SbFPsg5uY7EG8Ec(H`45|7MU!(9kFJ|q>vJxl#6^S*4=v-NJs9I+)H=|KsAlGnX$ zh5oFc-Nt8;xHHyM@4aW$VpT{AqQIHgzX!ZF)%TDS7ijp!DR8+PhZ+`43p?Zb%cF?J ztz*f<4{=&U{Zb-Kw?`k?Zj>klv=WPnx_Mo)kzAG$V)quK&07!JU!i0o8pMNk*^a#Jd(Bb5+oaOH_u6i?G^n_pBAPir*uHD#4><<< z*QgmY*RlIrbML+fn>nJL7+0TdjuCarPSmrHItGNdJg}Y4-PqPn#9uya?VbCwt@d4Z zXES}*9n{7*I`g*dqqd#e%!irVWxqDlcWtw6*LLP@X|rwbHuFKYwl{jO@~fWo0oIMpu8S39MT37h`DJ_EVMpw(h)>)j1oHl>`J7ns-Q2sLF z0(TW=rUiws2(B{=?HEBE7A$XVHHeqj)M{}hNH9#Jn3%r4z$~~ljIYfqi{*)tz`VSn z{sSYO^4emhr2ats3&qvdA}mI*@LV~kg`xQDv!^egJBrWH_&yfcm!5qA;t||qf%BXM zI5g0*CHoki1h=VVwzl6L@>&c12F%1LIn!c-4Qt1X~>L zX-*dx%BAY!RyTP`Q+~!M z!@Xi$F>m5qe11?dY4+k%=K;vBEcdK&80puHPr-e~c*U$5TaNmlXl0HvDF1r!Kx)(S z+e;RXfnb>Cms8MC`H2MmJom$;<$3~K{e-R?O&hXT5~qa;^%+08WP3F0;#3hnYJbq>y>8U~4)p0HEun%8HAMmL(>>9e6MConRPTB< z`D*Ib^s5>C69Zbk9?*B(?4Od}Q%}{sr*;YnR%B5_y@-C{qwPk&ke?rYM7`HNL+ooi z$As9=p)|f9YbpIpJI955zx4q|mTegsZZ|w|WTwKg308x8w;tI?T1IB7qv#vHW{dh} zs%Lf?nWDPA|8P~sc&Gf9A>PslCEnB;{m^Pz};fm2`ctgIekC(zc!=R55U|mS#-abg&IpiDlbKx-* zu95>M5#psY*qZjgiT`Z#YS*jTSGzaHuR^K@SAKM6%U!NMDaQy+HT{Y{Vi@}bSlB}0 z^xPc2+68w2ODH^3oU5)WecsS>7GGk)z+bKwYCN2nJ}R6}{a0*VVaG6Ikli&e7i$K8 zg>k$~wAGg?bk=dKJ#tf5yjx^P&aK^Y>d0e1Fbe!W`c7$U2rdUzy;UkyN*lLJ<+)O& zuvkWV8Q)I_=8a2R_TlpS)>d~Txxj>{3OL#}YJssC7+biW+O*_QX_j&Qe;1q5RvxkU z{4I`xOjsLpXdVzdz9`oEidRl15IXoOuC7!nC2yh!A6akkOY4nII$J?vZJktt6CdVX zFII0giAq;|jTQfUI${BErjOoO#?A5RV|>L?Tln4#-&=equoPT`PT109OHl}noM{U!eb78P#OBIAwnB+#F+y>no}}(XRH># zxoa-w#1oYe|Bw~dgrgPKG>T`yRIqMCfZ_EdiYblPL-O_N`lg;=r!uz){|QbGh5|`r zb$#&!VgP`#Aa(YI>FFC+U%2%A6b`r6@Xt~)+#%j*fd7h5g z?&KU#j_K|)PRx5^tot;BuhDsn4kuBrm&ol5O$R~|w6bU_;ec9}Lo8psb`rQJMb;?& zG-wf`Ec literal 0 HcmV?d00001 diff --git a/codes/cfd_mono.py b/codes/cfd_mono.py new file mode 100644 index 0000000..b6d17d4 --- /dev/null +++ b/codes/cfd_mono.py @@ -0,0 +1,327 @@ +from dolfin import * +import matplotlib.pyplot as plt +import numpy as np +import dolfin +from common import inout +from mpi4py import MPI +import sys +import os +# +# NAVIER STOKES PROBLEM IN THE AORTA with a MONOLITHIC SOLVER +# THIS SCRIPT INCLUDE THE 0-WINDKESSEL BOUNDARY CONDITION +# +# Written by Jeremias Garay L: j.e.garay.labra@rug.nl +# + +if '2017' in dolfin.__version__: + class MPI(MPI): + comm_world = mpi_comm_world() + + set_log_active(False) +else: + parameters["std_out_all_processes"] = False + + +def BACH(): + import os + tempof = 0.7 + semicorchea = 0.1*tempof + corchea = 0.2*tempof + negra = 0.4*tempof + blanca = 0.8*tempof + LA3 = 220 + SIb = 233.08 + SI = 246.94 + DO = 261 + REb = 277.18 + RE = 293.66 + FA = 349.23 + MIb = 311.13 + MI = 329.63 + SOL = 391 + LA = 440 + + os.system('play -V0 --no-show-progress --null --channels 1 synth %s sine %f' % (negra, DO)) + os.system('play -V0 --no-show-progress --null --channels 1 synth %s sine %f' % (negra, LA)) + os.system('play -V0 --no-show-progress --null --channels 1 synth %s sine %f' % (negra, SOL)) + os.system('play -V0 --no-show-progress --null --channels 1 synth %s sine %f' % (negra, FA)) + os.system('play -V0 --no-show-progress --null --channels 1 synth %s sine %f' % (semicorchea, MI)) + os.system('play -V0 --no-show-progress --null --channels 1 synth %s sine %f' % (semicorchea, FA)) + os.system('play -V0 --no-show-progress --null --channels 1 synth %s sine %f' % (corchea, SOL)) + os.system('play -V0 --no-show-progress --null --channels 1 synth %s sine %f' % (blanca, FA)) + +def flux(u,n,ds,idd): + Q = 0 + for k in idd: + Q += assemble(dot(u,n)*ds(k)) + return Q + +def save_outlet_data(options,Qin,Qout3,Qout4,Qout5,Qout6,Pin,Pout3,Pout4,Pout5,Pout6,dt): + # saving the fluxes + np.savetxt(options['outlets_path'] + 'fluxes/' + 'q_in_dt' + str(dt) + '.txt', Qin) + np.savetxt(options['outlets_path'] + 'fluxes/' + 'q3_dt' + str(dt) + '.txt', Qout3) + np.savetxt(options['outlets_path'] + 'fluxes/' + 'q4_dt' + str(dt) + '.txt', Qout4) + np.savetxt(options['outlets_path'] + 'fluxes/' + 'q5_dt' + str(dt) + '.txt', Qout5) + np.savetxt(options['outlets_path'] + 'fluxes/' + 'q6_dt' + str(dt) + '.txt', Qout6) + # saving the pressures + np.savetxt(options['outlets_path'] + 'pressures/' + 'p_in_dt' + str(dt) + '.txt', Pin) + np.savetxt(options['outlets_path'] + 'pressures/' + 'p3_dt' + str(dt) + '.txt', Pout3) + np.savetxt(options['outlets_path'] + 'pressures/' + 'p4_dt' + str(dt) + '.txt', Pout4) + np.savetxt(options['outlets_path'] + 'pressures/' + 'p5_dt' + str(dt) + '.txt', Pout5) + np.savetxt(options['outlets_path'] + 'pressures/' + 'p6_dt' + str(dt) + '.txt', Pout6) + +def windkessel_update(u0,n,ds,fluxes,press,pii,pii0,windkessel): + # Updating the time dependent windkessel parameters + if windkessel['C']: + for nk in windkessel['id']: + k = str(nk) + fluxes[k].assign(assemble(dot(u0,n)*ds(nk))) + pii0[k].assign(pii[k]) + pii[k].assign(windkessel['alpha'][k]*pii0[k] + windkessel['beta'][k]*fluxes[k]) + press[k].assign(windkessel['gamma'][k]*fluxes[k] + windkessel['alpha'][k]*pii0[k]) + + else: + for nk in windkessel['id']: + k = str(nk) + fluxes[k] = assemble(dot(u0,n)*ds(nk)) + press[k].assign( windkessel['R_p'][k]*assemble(dot(u0,n)*ds(nk))) + +def solv_NavierStokes(options): + + # Assign physical parameters + rho = Constant(options['density']) + mu = Constant(options['dynamic_viscosity']) + otheta = Constant(1-options['param']['theta']) + theta = Constant(options['param']['theta']) + Tf = options['Tf'] + dt = options['dt'] + dt_w = options['dt_write'] + Qin = np.zeros([int(Tf/dt)]) + Qout3 = np.zeros([int(Tf/dt)]) + Qout4 = np.zeros([int(Tf/dt)]) + Qout5 = np.zeros([int(Tf/dt)]) + Qout6 = np.zeros([int(Tf/dt)]) + Pin = np.zeros([int(Tf/dt)]) + Pout3 = np.zeros([int(Tf/dt)]) + Pout4 = np.zeros([int(Tf/dt)]) + Pout5 = np.zeros([int(Tf/dt)]) + Pout6 = np.zeros([int(Tf/dt)]) + barye2mmHg = 1/1333.22387415 + + # CREATING THE FILES + xdmf_u = XDMFFile(options['savepath']+'u.xdmf') + xdmf_p = XDMFFile(options['savepath']+'p.xdmf') + xdmf_u.parameters['rewrite_function_mesh'] = False + xdmf_p.parameters['rewrite_function_mesh'] = False + # LOADING THE MESH + #mesh = Mesh(options['mesh_path']) + #boundaries = MeshFunction('size_t', mesh, mesh.topology().dim()-1) + #boundaries = MarkBoundaries(boundaries) + + mesh = Mesh() + hdf = HDF5File(mesh.mpi_comm(), options['mesh_path'] , 'r') + hdf.read(mesh, '/mesh', False) + boundaries = MeshFunction('size_t', mesh , mesh.topology().dim() - 1) + hdf.read(boundaries, '/boundaries') + + # To save the boundaries information + #path2 = '/home/p283370/Desktop/marked_fine/boundaries.xdmf' + #XDMFFile(path2).write(boundaries) + # DEFINE FUNCTION SPACES + V = VectorElement('Lagrange', mesh.ufl_cell(), options['param']['Nvel']) + Q = FiniteElement('Lagrange', mesh.ufl_cell(), options['param']['Npress']) + TH = V * Q + W = FunctionSpace(mesh, TH) + # No-slip boundary condition for velocity on walls + noslip = Constant((0, 0, 0)) + inflow = Expression(('0','0','(-0.5*U*fabs(sin(w*t)) - 0.5*U*sin(w*t))*(t<0.7)'), degree=3,t=0,U=options['param']['U'], w=2*DOLFIN_PI/options['param']['period']) + bc_inflow = DirichletBC(W.sub(0), inflow, boundaries, 2) + bc_walls = DirichletBC(W.sub(0), noslip, boundaries, 1) + # COLLECTING THE BOUNDARY CONDITIONS + BCS = [bc_inflow,bc_walls] + u, p = TrialFunctions(W) + v, q = TestFunctions(W) + w = Function(W) + n = FacetNormal(mesh) + ds = Measure("ds", subdomain_data=boundaries) + h = CellDiameter(mesh) + f = Constant((0,0,0)) + u0, p0 = w.split() + + u_ = theta*u + (1 - theta)*u0 + theta_p = theta + p_ = theta_p*p + (1 - theta_p)*p0 + # The variational formulation + # Mass matrix + F = ( + (rho/dt)*dot(u - u0, v)*dx + + mu*inner(grad(u_), grad(v))*dx + - p_*div(v)*dx + q*div(u)*dx + + rho*dot(grad(u_)*u0, v)*dx + ) + + if options['stab']['temam']: + F += 0.5*rho*div(u0)*dot(u_, v)*dx + + if options['stab']['pspg']: + eps = Constant(options['stab']['epsilon']) + F += eps/mu*h**2*inner(grad(p_), grad(q))*dx + + if options['stab']['backflow']: + def abs_n(x): + return 0.5*(x - abs(x)) + + for nk in options['stab']['back_id']: + if rank==0: + print('adding backflow stabilization in border number:' + str(nk)) + F -= 0.5*rho*abs_n(dot(u0, n))*dot(u_, v)*ds(nk) + + a = lhs(F) + L = rhs(F) + + # Initialization of Windkessel Boundaries + if options['windkessel']['id']: + windkessel = options['windkessel'] + # Coeficients + fluxes = {str(k):[] for k in windkessel['id']} + pii0 = {str(k):[] for k in windkessel['id']} + pii = {str(k):[] for k in windkessel['id']} + press = {str(k):[] for k in windkessel['id']} + + if windkessel['C']: + for nk in windkessel['id']: + k = str(nk) + if rank==0: + print('Capacitance of windkessel model is: ', windkessel['C'][k]) + + # computing coeficients + windkessel['alpha'][k] = windkessel['R_d'][k]*windkessel['C'][k]/(windkessel['R_d'][k]*windkessel['C'][k] + options['dt']) + windkessel['beta'][k] = windkessel['R_d'][k]*(1-windkessel['alpha'][k]) + windkessel['gamma'][k] = windkessel['R_p'][k] + windkessel['beta'][k] + if rank==0: + print('Using 0-Windkessel complete at outlet number: ' + str(k)) + # setting initial values for flux, distal pressure and proximal pressure + fluxes[k] = Constant(0) + pii0[k] = Constant(47/barye2mmHg) + pii[k] = Constant(windkessel['alpha'][k]*pii0[k] + windkessel['beta'][k]*fluxes[k]) + press[k] = Constant(windkessel['gamma'][k]*fluxes[k] + windkessel['alpha'][k]*pii0[k]) + # Adding to RHS + L = L - dt*press[k]*dot(v,n)*ds(nk) + else: + for nk in windkessel['id']: + k = str(nk) + if rank==0: + print('Using 0-Windkessel reduced at outlet number: ' + str(nk)) + fluxes[k] = Constant(0) + press[k] = Constant(windkessel['R_p'][k]*0) + # Adding to RHS + L = L - dt*press[k]*dot(v,n)*ds(nk) + + + + # The static part of the matrix + A = assemble(a) + #b = assemble(L) + [bc.apply(A) for bc in BCS] + #[bc.apply(b) for bc in BCS] + #solv = LUSolver() + #solv.set_operator(A) + #solv.parameters['linear_solver'] = 'mumps' + #solv.parameters['reuse_factorization'] = True + u, p = w.split() + u.rename('velocity', 'u') + p.rename('pressure', 'p') + ind = 0 + t = dt + + ones = interpolate(Constant(1),W.sub(1).collapse()) + A2 = assemble(ones*ds(2)) + A3 = assemble(ones*ds(3)) + A4 = assemble(ones*ds(4)) + A5 = assemble(ones*ds(5)) + A6 = assemble(ones*ds(6)) + + checkcicle = int(options['checkpoint_dt']/options['dt']) + writecicle = int(options['checkpoint_dt']/options['dt_write']) + + while t<=Tf+dt: + + if options['windkessel']['id']: + windkessel_update(u,n,ds,fluxes,press,pii,pii0,windkessel) + # To solve + assemble(a, tensor=A) + b = assemble(L) + [bc.apply(A, b) for bc in BCS] + solve(A, w.vector(), b) + + Qin[ind] = flux(u,n,ds,[2]) + Qout3[ind] = flux(u,n,ds,[3]) + Qout4[ind] = flux(u,n,ds,[4]) + Qout5[ind] = flux(u,n,ds,[5]) + Qout6[ind] = flux(u,n,ds,[6]) + Pin[ind] = barye2mmHg*assemble(p*ds(2))/A2 + Pout3[ind] = barye2mmHg*assemble(p*ds(3))/A3 + Pout4[ind] = barye2mmHg*assemble(p*ds(4))/A4 + Pout5[ind] = barye2mmHg*assemble(p*ds(5))/A5 + Pout6[ind] = barye2mmHg*assemble(p*ds(6))/A6 + + if rank==0: + print('t = ',t) + # print('|u|:', norm(u0)) + # print('|p|:', norm(p0)) + # print('div(u):', assemble(div(u0)*dx)) + print('Dp = ',np.round(Pin[ind]-Pout3[ind],3),'mmHg') + + ind += 1 + if options['write_xdmf']: + if np.mod(ind,writecicle)<0.1 or ind==1: + xdmf_u.write(u, t) + xdmf_p.write(p, t) + + if np.mod(ind,checkcicle)<0.1 or ind==1: + if options['write_checkpoint']: + checkpath = options['savepath'] +'checkpoint/{i}/'.format(i=ind) + comm = u.function_space().mesh().mpi_comm() + inout.write_HDF5_data(comm, checkpath + '/u.h5', u, '/u', t=t) + inout.write_HDF5_data(comm, checkpath + '/p.h5', p, '/p', t=t) + + inflow.t = t + t += dt + + + # saving the data at outlets: fluxes and pressures + if options['write_outlets']: + if rank==0: + save_outlet_data(options,Qin,Qout3,Qout4,Qout5,Qout6,Pin,Pout3,Pout4,Pout5,Pout6,options['dt']) + + +if __name__ == '__main__': + + comm = MPI.COMM_WORLD + size = comm.Get_size() + rank = comm.Get_rank() + + if len(sys.argv) > 1: + if os.path.exists(sys.argv[1]): + inputfile = sys.argv[1] + if rank==0: + print('Found input file ' + inputfile) + else: + raise Exception('Command line arg given but input file does not exist:' + ' {}'.format(sys.argv[1])) + else: + raise Exception('An input file is required as argument!') + + if 'Zion' in os.popen('hostname').read(): + user = 'yeye' + np.set_printoptions(threshold=5) + + if 'fwn-bborg-5-166' in os.popen('hostname').read(): + user = 'p283370' + + if rank==0: + print('Welcome user {uss}'.format(uss=user)) + + options = inout.read_parameters(inputfile) + solv_NavierStokes(options) + diff --git a/codes/ktBLAST.py b/codes/ktBLAST.py new file mode 100644 index 0000000..7dadb9c --- /dev/null +++ b/codes/ktBLAST.py @@ -0,0 +1,870 @@ +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 kkmid: + 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 kkmid: + 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 NUMT0.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 + + + + diff --git a/codes/mesh_generator.py b/codes/mesh_generator.py new file mode 100755 index 0000000..5207cc8 --- /dev/null +++ b/codes/mesh_generator.py @@ -0,0 +1,71 @@ +from dolfin import * + + +mesh_in = '/home/yeye/Desktop/leomesh.xml' +mesh_out = '/home/yeye/Desktop/aorta.h5' +mesh = Mesh(mesh_in) + +hdf = HDF5File(mesh.mpi_comm(), mesh_out, 'w') +boundaries = MeshFunction('size_t', mesh,2) + +marked = 1 +testmesh = 0 + +hdf.write(mesh, '/mesh') + +if marked==1: + + class Inlet(SubDomain): + def inside(self, x, on_boundary): + return on_boundary and between(x[0],(0.1975,0.1989)) and between(x[2],(0.07,0.1)) + + class Outlet(SubDomain): + def inside(self, x, on_boundary): + return on_boundary and between(x[0],(0.1975,0.1989)) and between(x[2],(0,0.04)) + + class Walls(SubDomain): + def inside(self, x, on_boundary): + return on_boundary + + + outlet = Outlet() + inlet = Inlet() + walls = Walls() + + boundaries.set_all(0) + walls.mark(boundaries,1) + outlet.mark(boundaries,3) + inlet.mark(boundaries,2) + + + + +hdf.write(boundaries, '/boundaries') +hdf.close() + + + +if testmesh: + print('Testing Mesh...') + meshname = mesh_out + pathtoB = '/home/yeye/Desktop/boundaries.xdmf' + mesh = Mesh() + hdf = HDF5File(mesh.mpi_comm(), meshname , 'r') + hdf.read(mesh, '/mesh', False) + boundaries = MeshFunction('size_t', mesh , mesh.topology().dim() - 1) + hdf.read(boundaries, '/boundaries') + # To save the boundaries information + XDMFFile(pathtoB).write(boundaries) + print('Boundary info printed in ' + pathtoB) + + + + + + + + + + + +