def _check_data_size(par, data, sigmodel): if data.ndim == 5: pass elif data.ndim == 4 and "IRLL" in sigmodel: Nproj_new = 13 print("4D Data passed and IRLL model used. Reordering Projections " "into " + str(Nproj_new) + " Spokes/Frame") [NC, reco_Slices, Nproj, N] = data.shape NScan = np.floor_divide(Nproj, Nproj_new) par["Nproj_measured"] = Nproj Nproj = Nproj_new data = np.require( np.transpose( np.reshape(data[..., :Nproj * NScan, :], (NC, reco_Slices, NScan, Nproj, N)), (2, 0, 1, 3, 4), ), requirements="C", ) par["traj"] = np.require( np.reshape(par["traj"][:Nproj * NScan, :], (NScan, Nproj, N)), requirements="C", ) par["dcf"] = np.sqrt(goldcomp.cmp(par["traj"])) par["dcf"] = np.require(np.abs(par["dcf"]), par["DTYPE_real"], requirements="C") elif data.ndim == 4 and "ImageReco" in sigmodel: data = data[None] else: raise ValueError("Wrong data dimension / model incompatible.") return data
def setupPar(par): par["NScan"] = 10 par["NC"] = 8 par["NSlice"] = 12 par["dimX"] = 128 par["dimY"] = 128 par["Nproj"] = 34 par["N"] = 256 par["unknowns_TGV"] = 2 par["unknowns_H1"] = 0 par["unknowns"] = 2 par["dz"] = 1 par["weights"] = np.array([1, 1]) par["overlap"] = 1 file = h5py.File('./test/smalltest.h5', 'r') par["traj"] = file['real_traj'][()].astype(DTYPE) + \ 1j*file['imag_traj'][()].astype(DTYPE) par["dcf"] = np.sqrt(np.array(goldcomp.cmp(par["traj"]), dtype=DTYPE_real)).astype(DTYPE_real) par["dcf"] = np.require(np.abs(par["dcf"]), DTYPE_real, requirements='C') par["fft_dim"] = (-2, -1)
def est_coils(data, par, file, args, off): """Estimate coil sensitivity profiles. This function estimates coil sensitivity profiles based on the non-linear inversion method from Uecker et al. It first checks if coil information is present in the given data file and if the size matches the number of slices that should be reconstructed. If the check fails, new coil sensitivity information is estimated and saved to the data file. Parameters ---------- data : numpy.array The complex k-space data. par : dict Parameter dictionary. file : h5py.File A h5py.File possibly containing the coil profiles. Also used for storing newly computed profile information. args : argparse.ArgumentParser Commandline arguments passed to the script. off : int A possible offset of the zero slice. Returns ------- numpy.array The complex coilsensitivity information. """ ########################################################################### # Initiate parallel interface ############################################# ########################################################################### c = ipp.Client() nlinvNewtonSteps = 6 nlinvRealConstr = False if args.sms or "Coils_real" in list(file.keys()): print("Using precomputed coil sensitivities") slices_coils = file['Coils_real'][()].shape[1] par["C"] = file['Coils_real'][ :, int(slices_coils / 2) - int(np.floor((par["NSlice"]) / 2)) + off: int(slices_coils / 2) + int(np.ceil(par["NSlice"] / 2)) + off, ...] + 1j * file['Coils_imag'][ :, int(slices_coils / 2) - int(np.floor((par["NSlice"]) / 2)) + off: int(slices_coils / 2) + int(np.ceil(par["NSlice"] / 2)) + off, ...] par["C"] = par["C"].astype(par["DTYPE"]) elif not args.sms and "Coils" in list(file.keys()): if args.trafo and not file['Coils'].shape[1] >= par["NSlice"]: traj_coil = np.reshape( par["traj"], (par["NScan"] * par["Nproj"], par["N"])) dcf_coil = np.sqrt(goldcomp.cmp(traj_coil)) dcf_coil = np.require(dcf_coil, requirements='C', dtype=par["DTYPE_real"]) par["C"] = np.zeros( (par["NC"], par["NSlice"], par["dimY"], par["dimX"]), dtype=par["DTYPE"]) par["phase"] = np.zeros( (par["NSlice"], par["dimY"], par["dimX"]), dtype=par["DTYPE"]) par_coils = {} par_coils["traj"] = traj_coil par_coils["dcf"] = dcf_coil par_coils["N"] = par["N"] par_coils["NScan"] = 1 par_coils["NC"] = 1 par_coils["NSlice"] = 1 par_coils["ctx"] = par["ctx"] par_coils["queue"] = par["queue"] par_coils["dimX"] = par["dimX"] par_coils["dimY"] = par["dimY"] par_coils["fft_dim"] = [-2, -1] FFT = utils.NUFFT(par_coils) result = [] for i in range(0, (par["NSlice"])): sys.stdout.write( "Computing coil sensitivity map of slice %i \r" % (i)) sys.stdout.flush() # RADIAL PART combinedData = np.transpose( data[:, :, i, :, :], (1, 0, 2, 3)) combinedData = np.require( np.reshape( combinedData, (1, par["NC"], 1, par["NScan"] * par["Nproj"], par["N"])), requirements='C') * dcf_coil tmp_coilData = clarray.zeros( FFT.queue, (1, 1, 1, par["dimY"], par["dimX"]), dtype=par["DTYPE"]) coilData = np.zeros( (par["NC"], par["dimY"], par["dimX"]), dtype=par["DTYPE"]) for j in range(par["NC"]): tmp_combinedData = clarray.to_device( FFT.queue, combinedData[None, :, j, ...]) FFT.FFTH(tmp_coilData, tmp_combinedData) coilData[j, ...] = np.squeeze(tmp_coilData.get()) combinedData = np.require( np.fft.fft2( coilData, norm=None) / np.sqrt( par["dimX"] * par["dimY"]), dtype=par["DTYPE"], requirements='C') dview = c[int(np.floor(i * len(c) / par["NSlice"]))] result.append( dview.apply_async( nlinvns.nlinvns, combinedData, nlinvNewtonSteps, True, nlinvRealConstr, DTYPE=par["DTYPE"], DTYPE_real=par["DTYPE_real"])) for i in range(par["NSlice"]): par["C"][:, i, :, :] = result[i].get()[2:, -1, :, :] sys.stdout.write("slice %i done \r" % (i)) sys.stdout.flush() if not nlinvRealConstr: par["phase"][i, :, :] = np.exp( 1j * np.angle(result[i].get()[0, -1, :, :])) # standardize coil sensitivity profiles sumSqrC = np.sqrt( np.sum( (par["C"] * np.conj( par["C"])), 0)) par["InScale"] = sumSqrC if par["NC"] == 1: par["C"] = sumSqrC else: par["C"] = par["C"] / \ np.tile(sumSqrC, (par["NC"], 1, 1, 1)) del file['Coils'] del FFT file.create_dataset( "Coils", par["C"].shape, dtype=par["C"].dtype, data=par["C"]) file.flush() elif not args.trafo and not \ file['Coils'].shape[1] >= par["NSlice"]: par["C"] = np.zeros( (par["NC"], par["NSlice"], par["dimY"], par["dimX"]), dtype=par["DTYPE"]) par["phase"] = np.zeros( (par["NSlice"], par["dimY"], par["dimX"]), dtype=par["DTYPE"]) result = [] combinedData = np.sum(data, 0) for i in range(0, (par["NSlice"])): sys.stdout.write( "Computing coil sensitivity map of slice %i \r" % (i)) sys.stdout.flush() tmp = combinedData[:, i, ...] dview = c[int(np.floor(i * len(c) / par["NSlice"]))] result.append( dview.apply_async( nlinvns.nlinvns, tmp, nlinvNewtonSteps, True, nlinvRealConstr, DTYPE=par["DTYPE"], DTYPE_real=par["DTYPE_real"])) for i in range(par["NSlice"]): par["C"][:, i, :, :] = result[i].get()[2:, -1, :, :] sys.stdout.write("slice %i done \r" % (i)) sys.stdout.flush() if not nlinvRealConstr: par["phase"][i, :, :] = np.exp( 1j * np.angle(result[i].get()[0, -1, :, :])) # standardize coil sensitivity profiles sumSqrC = np.sqrt( np.sum( (par["C"] * np.conj( par["C"])), 0)) par["InScale"] = sumSqrC if par["NC"] == 1: par["C"] = sumSqrC else: par["C"] = par["C"] / \ np.tile(sumSqrC, (par["NC"], 1, 1, 1)) del file['Coils'] file.create_dataset( "Coils", par["C"].shape, dtype=par["C"].dtype, data=par["C"]) file.flush() else: print("Using precomputed coil sensitivities") slices_coils = file['Coils'].shape[1] par["C"] = \ file['Coils'][ :, int(slices_coils / 2) - int(np.floor((par["NSlice"]) / 2)) + off: int(slices_coils / 2) + int(np.ceil(par["NSlice"] / 2)) + off, ...] par["C"] = par["C"].astype(par["DTYPE"]) else: if args.trafo: traj_coil = np.reshape( par["traj"], (par["NScan"] * par["Nproj"], par["N"])) dcf_coil = np.sqrt(goldcomp.cmp(traj_coil)) dcf_coil = np.require(dcf_coil, requirements='C', dtype=par["DTYPE_real"]) par["C"] = np.zeros( (par["NC"], par["NSlice"], par["dimY"], par["dimX"]), dtype=par["DTYPE"]) par["phase"] = np.zeros( (par["NSlice"], par["dimY"], par["dimX"]), dtype=par["DTYPE"]) par_coils = {} par_coils["traj"] = traj_coil par_coils["dcf"] = dcf_coil par_coils["dimX"] = par["dimX"] par_coils["dimY"] = par["dimY"] par_coils["N"] = par["N"] par_coils["NScan"] = 1 par_coils["NC"] = 1 par_coils["NSlice"] = 1 par_coils["ctx"] = par["ctx"] par_coils["queue"] = par["queue"] par_coils["fft_dim"] = [-2, -1] FFT = utils.NUFFT(par_coils) result = [] for i in range(0, (par["NSlice"])): sys.stdout.write( "Computing coil sensitivity map of slice %i \r" % (i)) sys.stdout.flush() combinedData = np.transpose(data[:, :, i, :, :], (1, 0, 2, 3)) combinedData = np.require( np.reshape( combinedData, (1, par["NC"], 1, par["NScan"] * par["Nproj"], par["N"])), requirements='C') * dcf_coil tmp_coilData = clarray.zeros( FFT.queue, (1, 1, 1, par["dimY"], par["dimX"]), dtype=par["DTYPE"]) coilData = np.zeros( (par["NC"], par["dimY"], par["dimX"]), dtype=par["DTYPE"]) for j in range(par["NC"]): tmp_combinedData = clarray.to_device( FFT.queue, combinedData[None, :, j, ...]) FFT.FFTH(tmp_coilData, tmp_combinedData) coilData[j, ...] = np.squeeze(tmp_coilData.get()) combinedData = np.require( np.fft.fft2( coilData, norm=None) / np.sqrt( par["dimX"] * par["dimY"]), dtype=par["DTYPE"], requirements='C') dview = c[int(np.floor(i * len(c) / par["NSlice"]))] result.append( dview.apply_async( nlinvns.nlinvns, combinedData, nlinvNewtonSteps, True, nlinvRealConstr, DTYPE=par["DTYPE"], DTYPE_real=par["DTYPE_real"])) for i in range(par["NSlice"]): par["C"][:, i, :, :] = result[i].get()[2:, -1, :, :] sys.stdout.write("slice %i done \r" % (i)) sys.stdout.flush() if not nlinvRealConstr: par["phase"][i, :, :] = np.exp( 1j * np.angle(result[i].get()[0, -1, :, :])) # standardize coil sensitivity profiles sumSqrC = np.sqrt( np.sum( (par["C"] * np.conj( par["C"])), 0)) par["InScale"] = sumSqrC if par["NC"] == 1: par["C"] = sumSqrC else: par["C"] = par["C"] / np.tile(sumSqrC, (par["NC"], 1, 1, 1)) del FFT else: par["C"] = np.zeros( (par["NC"], par["NSlice"], par["dimY"], par["dimX"]), dtype=par["DTYPE"]) par["phase"] = np.zeros( (par["NSlice"], par["dimY"], par["dimX"]), dtype=par["DTYPE"]) result = [] combinedData = np.sum(data, 0) for i in range(0, (par["NSlice"])): sys.stdout.write( "Computing coil sensitivity map of slice %i \r" % (i)) sys.stdout.flush() # RADIAL PART tmp = combinedData[:, i, ...] dview = c[int(np.floor(i * len(c) / par["NSlice"]))] result.append( dview.apply_async( nlinvns.nlinvns, tmp, nlinvNewtonSteps, True, nlinvRealConstr, DTYPE=par["DTYPE"], DTYPE_real=par["DTYPE_real"])) for i in range(par["NSlice"]): par["C"][:, i, :, :] = result[i].get()[2:, -1, :, :] sys.stdout.write("slice %i done \r" % (i)) sys.stdout.flush() if not nlinvRealConstr: par["phase"][i, :, :] = np.exp( 1j * np.angle(result[i].get()[0, -1, :, :])) # standardize coil sensitivity profiles sumSqrC = np.sqrt( np.sum( (par["C"] * np.conj( par["C"])), 0)) par["InScale"] = sumSqrC if par["NC"] == 1: par["C"] = sumSqrC[None, ...] else: par["C"] = par["C"] / np.tile(sumSqrC, (par["NC"], 1, 1, 1)) file.create_dataset( "Coils", par["C"].shape, dtype=par["C"].dtype, data=par["C"]) file.flush()
def _read_data_from_file(par, myargs): reco_Slices = myargs.slices dimX, dimY, NSlice = (par["file"].attrs["image_dimensions"]).astype(int) if reco_Slices == -1: reco_Slices = NSlice off = 0 if myargs.sms or myargs.is3Ddata: data = par["file"]["real_dat"][()].astype( par["DTYPE"]) + 1j * par["file"]["imag_dat"][ ()].astype(par["DTYPE"]) else: data = (par["file"]["real_dat"][..., int(NSlice / 2) - int(np.floor((reco_Slices) / 2)) + off:int(NSlice / 2) + int(np.ceil(reco_Slices / 2)) + off, :, :, ].astype(par["DTYPE"]) + 1j * par["file"]["imag_dat"] [..., int(NSlice / 2) - int(np.floor((reco_Slices) / 2)) + off:int(NSlice / 2) + int(np.ceil(reco_Slices / 2)) + off, :, :, ].astype(par["DTYPE"])) dimreduction = 0 if myargs.trafo: if "real_traj" in par["file"].keys(): par["traj"] = np.stack( ( par["file"]["imag_traj"][()].astype(par["DTYPE_real"]), par["file"]["real_traj"][()].astype(par["DTYPE_real"]), ), axis=-1, ) else: par["traj"] = par["file"]["traj"][()].astype(par["DTYPE_real"]) if "dcf" in par["file"].keys(): par["dcf"] = np.sqrt(par["file"]["dcf"][()].astype( par["DTYPE_real"])) else: par["dcf"] = np.sqrt(goldcomp.cmp(par["traj"])) par["dcf"] = np.require(np.abs(par["dcf"]), par["DTYPE_real"], requirements="C") # Check if traj is scaled max_traj_val = np.max(np.abs(par["traj"])) if np.allclose(max_traj_val, 0.5, rtol=1e-1): par["traj"] *= dimX elif np.allclose(max_traj_val, 1, rtol=1e-1): par["traj"] *= dimX / 2 overgrid_factor_a = 1 / np.linalg.norm( par["traj"][..., -2, :] - par["traj"][..., -1, :], axis=-1) overgrid_factor_b = 1 / np.linalg.norm( par["traj"][..., 0, :] - par["traj"][..., 1, :], axis=-1) par["ogf"] = np.min((overgrid_factor_a, overgrid_factor_b)) print("Estimated OGF: ", par["ogf"]) par["traj"] *= par["ogf"] else: par["traj"] = None par["dcf"] = None #### Need to rework this as it might introduce unknown errors in #### Cartesian data! if np.max(utils.prime_factors(data.shape[-1])) > 13: print("Samples along the spoke need to have their largest prime factor" " to be 13 or lower. Finding next smaller grid.") dimreduction = 2 while np.max(utils.prime_factors(data.shape[-1] - dimreduction)) > 13: dimreduction += 2 print("Decrease grid size by %i" % dimreduction) dimX -= dimreduction dimY -= dimreduction if myargs.trafo: data = np.require( data[..., int(dimreduction / 2):data.shape[-1] - int(dimreduction / 2)], requirements="C", ) par["traj"] = np.require( par["traj"][..., int(dimreduction / 2):par["traj"].shape[-1] - int(dimreduction / 2), ], requirements="C", ) par["dcf"] = np.sqrt(goldcomp.cmp(par["traj"])) par["dcf"] = np.require(np.abs(par["dcf"]), par["DTYPE_real"], requirements="C") else: data = np.require( data[..., int(dimreduction / 2):data.shape[-1] - int(dimreduction / 2), int(dimreduction / 2):data.shape[-1] - int(dimreduction / 2), ], requirements="C", ) return data, dimX, dimY, NSlice, reco_Slices, dimreduction, off
def _read_data_from_file(par, myargs): reco_Slices = myargs.slices dimX, dimY, NSlice = ((par["file"].attrs['image_dimensions']).astype(int)) if reco_Slices == -1: reco_Slices = NSlice off = 0 if myargs.sms: data = par["file"]['real_dat'][()].astype(par["DTYPE"])\ + 1j*par["file"]['imag_dat'][()].astype(par["DTYPE"]) else: data = par["file"]['real_dat'][ ..., int(NSlice/2)-int(np.floor((reco_Slices)/2))+off: int(NSlice/2)+int(np.ceil(reco_Slices/2))+off, :, : ].astype(par["DTYPE"])\ + 1j*par["file"]['imag_dat'][ ..., int(NSlice/2)-int(np.floor((reco_Slices)/2))+off: int(NSlice/2)+int(np.ceil(reco_Slices/2))+off, :, : ].astype(par["DTYPE"]) dimreduction = 0 if myargs.trafo: par["traj"] = par["file"]['real_traj'][()].astype(par["DTYPE"]) + \ 1j*par["file"]['imag_traj'][()].astype(par["DTYPE"]) par["dcf"] = np.sqrt(goldcomp.cmp(par["traj"])) par["dcf"] = np.require(np.abs(par["dcf"]), par["DTYPE_real"], requirements='C') else: par["traj"] = None par["dcf"] = None if np.max(utils.prime_factors(data.shape[-1])) > 13: print("Samples along the spoke need to have their largest prime factor" " to be 13 or lower. Finding next smaller grid.") dimreduction = 2 while np.max(utils.prime_factors(data.shape[-1] - dimreduction)) > 13: dimreduction += 2 print('Decrease grid size by %i' % dimreduction) dimX -= dimreduction dimY -= dimreduction if myargs.trafo: data = np.require(data[..., int(dimreduction / 2):data.shape[-1] - int(dimreduction / 2)], requirements='C') par["traj"] = np.require(par["traj"][..., int(dimreduction / 2):par["traj"].shape[-1] - int(dimreduction / 2)], requirements='C') par["dcf"] = np.sqrt(goldcomp.cmp(par["traj"])) par["dcf"] = np.require(np.abs(par["dcf"]), par["DTYPE_real"], requirements='C') else: data = np.require(data[..., int(dimreduction / 2):data.shape[-1] - int(dimreduction / 2), int(dimreduction / 2):data.shape[-1] - int(dimreduction / 2)], requirements='C') return data, dimX, dimY, NSlice, reco_Slices, dimreduction, off