def __init__(self, fid_data, procpar, fidheader): def get_arrayed_AP(p): """ check for arrayed acquisition parameters in procpar return dictionary {par : array_length} """ AP_dict = {} for par in ['tr', 'te', 'fa']: pass return AP_dict self.fid_data = fid_data self.p = procparReader(procpar).read() self.fid_header = fidheader self.rcvrs = str(self.p['rcvrs']).count('y') self.arrayed_AP = get_arrayed_AP(self.p) apptype = self.p['apptype'] # decoding skipint parameter print('Making k-space for '+ str(apptype)+str(self.p['seqfil'])+\ ' seqcon: '+str(self.p['seqcon']))
def load_data(): # returns list of data def ifft(inkdata): inkdata = np.fft.fftshift(inkdata, axes=(2, 3)) ifft_data = np.fft.ifft2(inkdata, axes=(2, 3), norm='ortho') ifft_data = np.fft.ifftshift(ifft_data, axes=(2, 3)) return ifft_data folder = '/home/david/dev/dixon/s_2018080901' name_list = glob.glob(folder + '/fsems2*img') #ind = [0,3,6] ind = [0, 1, 2, 3, 4, 5, 6] rawre = sorted([i for i in name_list if 'rawRE' in i]) rawim = sorted([i for i in name_list if 'rawIM' in i]) #print('\n'.join(rawim)) #getting only the -pi, 0, pi combined_names = [[rawre[i], rawim[i]] for i in ind] data = [] roshift = [] for item in combined_names: procpar = (item[0] + '/procpar') #print(procpar) print(item[0]) ppr = procparReader(item[0] + '/procpar') roshift.append(float(ppr.read()['roshift'])) hdr, data_re = fdfReader(item[0], 'out').read() hdr, data_im = fdfReader(item[1], 'out').read() cdata = np.vectorize(complex)(data_re[0, ...], data_im[0, ...]) data.append(ifft(cdata)) print(data[0].shape) print(roshift) return data, roshift, procpar
def __init__(self, data, procpar, fid_path=None): """ data = numpy.ndarray(phase, read, slice, echo) procpar = /path/to/procpar """ self.fid = fid_path self.procpar = procpar self.p = procparReader(procpar).read() self.data = data
def __init__(self, data, procpar, fitmethod): self.data = data self.procpar = procpar self.fitmethod = fitmethod ppr = procparReader(procpar) self.ppdict = ppr.read() te = float(self.ppdict['te']) ne = int(self.ppdict['ne']) self.echo_times = [i*te for i in range(1,ne+1)] # echo times in seconds
def __init__(self, kspace, procpar, skiptab=None, skipint=None): """ kspace = np.ndarray([receivers, phase, read, slice, echo]) procpar = /procpar/file/path For CS reconstruction: skiptab = 'y' or 'n' procpar parameter skipint = procpar parameter to show which k space lines are excluded """ self.skipint = skipint self.skiptab = skiptab self.kspace_data = kspace self.p = procparReader(procpar).read()
def __init__(self, data, procpar, fitmethod, skipfirstecho): self.procpar = procpar self.fitmethod = fitmethod ppr = procparReader(procpar) self.ppdict = ppr.read() te = float(self.ppdict['te']) ne = int(self.ppdict['ne']) if skipfirstecho == False: self.data = data self.echo_times = [i * te for i in range(1, ne + 1) ] # echo times in seconds elif skipfirstecho == True: self.data = data[:, :, :, 1:] self.echo_times = [i * te for i in range(2, ne + 1) ] # echo times in seconds
def fid2nii(indir, out=None, saveprocpar=True, save_kspace=False, save_imgspace=True): if not os.path.isdir(indir): raise (Exception('Please specify input fid directory')) if out == None: # if output is not given, take fid as basename for new dir out = indir[:-4] + '.nifti/' if not os.path.exists(out): os.makedirs(out) fid = indir + '/fid' procpar = indir + '/procpar' ppdict = procparReader(procpar).read() fid_data, fid_header = fidReader(fid, procpar).read() kspacemaker = kSpaceMaker(fid_data, procpar, fid_header) kspace = kspacemaker.make() imgspace = imgSpaceMaker(kspace, procpar).make() kspace_real = [] # put separate channel data into separate lements of list kspace_imag = [] for i in range(len(ppdict['rcvrs'])): kspace_real.append(np.real(kspace[i, ...])) kspace_imag.append(np.imag(kspace[i, ...])) writer1 = niftiWriter(procpar, kspace_real[-1]) writer1.write(out + 'kspace_real_ch' + str(i)) writer2 = niftiWriter(procpar, kspace_imag[-1]) writer2.write(out + 'kspace_imag_ch' + str(i)) sumimg = np.sum(np.absolute(imgspace), axis=0) writer_img = niftiWriter(procpar, sumimg) writer_img.write(out + 'imgspace_sum') if saveprocpar == True: copyfile(procpar, out + '/procpar')
def __init__(self, procpar, kspace_cs, kspace_orig, reconpar=None): """ INPUT: procpar : path to procpar file kspace_cs : zerofilled cs kspace in numpy array reconpar: dictionary, ALOHA recon parameters keys: filter_size rcvrs cs_dim recontype """ def get_recontype(reconpar): if 'angio' in self.p['pslabel']: recontype = 'kx-ky_angio' elif 'mems' in self.p['pslabel']: recontype = 'k-t' return recontype def get_reconpar(): pass self.p = procparReader(procpar).read() recontype = get_recontype(reconpar) rcvrs = self.p['rcvrs'].count('y') self.rp = {'filter_size' : FILTER_SIZE ,\ 'cs_dim' : CS_DIM ,\ 'ro_dim' : RO_DIM, \ 'rcvrs' : rcvrs , \ 'recontype' : recontype,\ 'timedim' : 4,\ 'stages' : STAGES,\ 'virtualcoilboost' : False} print(self.rp) self.kspace_cs = np.array(kspace_cs, dtype='complex64') self.kspace = np.array(kspace_orig, dtype='complex64')
def read(self): #---------------- auxiliary functions for read method ----------------- def preproc_fdf(fdf): with open(fdf,'rb') as openFdf: fdata = bytearray(openFdf.read()) nul = fdata.find(b'\x00') header = fdata[:nul] data = fdata[nul+1:] return (header,data) # ----------parse fdf header and return into a dictionary -------------- def parse_header(header): keys_to_parse = sorted(['rank','roi','location','spatial_rank',\ 'matrix','orientation',\ 'studyid','gap','pe_size','ro_size',\ 'pe2_size', 'abscissa',\ 'storage']) to_delete = ('char','float','int') header = header.decode('ascii').split('\n') header_dict = {} for line in header: # some formatting of header if self.printlines: print(line) for item in to_delete: if line.startswith(item): line = line.split(item,1) break try: line = line[1].lstrip() line = line.lstrip('*').rstrip(';') if '[]' in line: line = line.replace('[]','') if '{' in line: line = line.replace('{','(') if '}' in line: line = line.replace('}',')') if ' ' in line: line = line.replace(' ','') line = line.split('=') header_dict[line[0]] = line[1] except: continue for item in keys_to_parse: if item in header_dict.keys(): if item == 'abscissa': tempval = header_dict[item][1:-1];''.join(tempval) tempval = tempval.replace('"','') header_dict[item] = tuple([k for k in tempval.split(',')]) if item == 'matrix': tempval = header_dict[item][1:-1];''.join(tempval) header_dict[item] = tuple([int(k) for k in tempval.split(',')]) if item == 'roi': tempval = header_dict[item][1:-1];''.join(tempval) header_dict[item] = tuple([float(k) for k in tempval.split(',')]) if item == 'ro_size' or item == 'pe_size' or item == 'pe2_size': header_dict[item] = int(header_dict[item]) if item == 'storage': tempval = header_dict[item];''.join(tempval) tempval = tempval.replace('"','') header_dict[item] = str(tempval) if item == 'orientation': tempval = header_dict[item][1:-1];''.join(tempval) header_dict[item] = tuple([float(k) for k in tempval.split(',')]) if item == 'location': tempval = header_dict[item][1:-1];''.join(tempval) header_dict[item] = tuple([float(k) for k in tempval.split(',')]) if item == 'gap': header_dict[item] = float(header_dict[item]) if item == 'slices': header_dict[item] = int(header_dict[item]) if item == 'TR': header_dict[item] = float(header_dict[item])/1000 return header_dict #----------process bynary data based on header-------------------- def prepare_data(binary_data): matrix = self.header_dict['matrix'] if self.header_dict['storage'] == 'float' and \ self.header_dict['bits'] == '32': dt = np.dtype('float32'); dt = dt.newbyteorder('<') else: print('') print('error: data type incorrectly specified in "prepare_data"\n') return -1 img_data = np.frombuffer(binary_data, dtype=dt) img_data = np.reshape(img_data,matrix) return img_data #-------------------------------------------------------------------------------------- # main read method #-------------------------------------------------------------------------------------- if os.path.isdir(self.path): self.procpar = str(self.path)+'/procpar' fdf_list = sorted(glob.glob(str(self.path)+'/*.fdf')) (header, data) = preproc_fdf(fdf_list[0]) # run preproc once to get header ppr = procparReader(self.procpar) self.ppdict = ppr.read() else: try: ppr = procparReader(self.procpar) self.ppdict = ppr.read() except: print('\nfdfReader.read() warning : Please specify procpar file!\n') fdf_list =[self.path] (header, data) = preproc_fdf(self.path) self.header_dict = parse_header(header) # ------------------------process if 3d ------------------------- if self.header_dict['spatial_rank'] == '"3dfov"': full_data = [] time_concat = [] time = len([1 for i in fdf_list if 'slab001' in i]) for i in fdf_list: # only 1 item, but there migh be more in future (header, data) = preproc_fdf(i) img_data = prepare_data(data) full_data.append(img_data) # full data in one list self.data_array = np.asarray(full_data) #self.data_array = np.swapaxes(self.data_array, 0,3) #------- -----------------process if 2d------------------------------------ elif self.header_dict['spatial_rank'] == '"2dfov"': full_data = [] time_concat = [] time = len([1 for i in fdf_list if 'slice001' in i]) for i in fdf_list: (header, data) = preproc_fdf(i) img_data = prepare_data(data) img_data = np.expand_dims(np.expand_dims(img_data,2),3) # expand 2d to 4d full_data.append(img_data) # full data in one list # make sublists slice_list =[full_data[i:i+time] for i in range(0,len(full_data),time)] for aslice in slice_list: time_concat.append(np.concatenate(tuple(aslice),axis=3)) slice_time_concat = np.concatenate(time_concat, axis=2) #slice+time concatenated self.data_array = slice_time_concat if str(self.ppdict['orient']) == 'trans90': # vomit inducing method to properly flip data print('found orientation') self.data_array = np.swapaxes(self.data_array, 0, 1) # --------------------process if 1d------------------------ TODO ???? elif self.header_dict['spatial_rank'] == '"1dfov"': pass return (self.header_dict, self.data_array)
def __init__(self, procpar, data): ppr = procparReader(procpar) self.ppdict = ppr.read() self.data = data seqfil = self.ppdict['seqfil'] seqcon = self.ppdict['seqcon']
def run(self): def make_fieldmap(minus_pi_data, plus_pi_data, procpar): """ Make phase correction factor from minus Pi shifted and plus Pi shifted data. Does unwrapping with prelude in two steps: first step is preliminary field map with output mask, then this output mask is holefilled and the unwrapping is done again """ output_name_fieldmap = self.proc_dir + '/fieldmap_wrapped' output_name_fieldmap_uw = self.proc_dir + '/fieldmap_unwrapped' output_name_fieldmap_mask = self.proc_dir + '/fieldmap_premask' output_name_fieldmap_mask_corr = self.proc_dir + '/fieldmap_mask' magnitude_name_for_prelude_corr = self.proc_dir + '/masked_abs' data = np.multiply(plus_pi_data, np.conj(minus_pi_data)) fieldmap = np.arctan2(np.imag(data), np.real(data)) niftiwriter = niftiWriter(procpar, fieldmap) niftiwriter.write(output_name_fieldmap) print('Unwrapping fieldmap ...') # make initial field map os.system('prelude -p '+output_name_fieldmap+' -a '+magnitude_name_for_prelude+ \ ' -u '+output_name_fieldmap_uw+' --savemask='+output_name_fieldmap_mask) # close gaps in mask os.system('fslmaths ' + output_name_fieldmap_mask + ' -fillh ' + output_name_fieldmap_mask_corr) # make new absolute with mask os.system('fslmaths '+magnitude_name_for_prelude+' -mul '+output_name_fieldmap_mask_corr+\ ' '+magnitude_name_for_prelude_corr) # make final field map os.system('prelude -p '+output_name_fieldmap+' -a '+magnitude_name_for_prelude_corr+ \ ' -u '+output_name_fieldmap_uw) print('Fieldmap done!') return def inverse_fourier_transform2D(kspace_data): # changed axes 2,3 print('pproc kdata shape {}'.format(kspace_data.shape)) kspace_data = np.fft.fftshift(kspace_data, axes=(0, 1)) imgspace_data = np.fft.ifft2(kspace_data, axes=(0, 1), norm='ortho') imgspace_data = np.fft.ifftshift(imgspace_data, axes=(0, 1)) return imgspace_data if not os.path.exists(self.proc_dir): os.makedirs(self.proc_dir) if not self.preproc_from_fid: open(self.preproc_data, 'w').close() procpar = [] roshift = [] for item in self.combined_names: # combined_names is a list of lists containing real and imaginary parts procpar.append(item[0] + '/procpar') ppr = procparReader(item[0] + '/procpar') shift = int(float(ppr.read()['roshift']) * 1000000) # write it in microsec for naming roshift.append(float(ppr.read()['roshift'])) hdr, data_re = fdfReader(item[0], 'out').read() hdr, data_im = fdfReader(item[1], 'out').read() kspace_data = np.vectorize(complex)(data_re, data_im) imgspace_data = inverse_fourier_transform2D(kspace_data) magnitude_data = np.absolute(imgspace_data) phase_data = np.arctan2(np.imag(imgspace_data), np.real(imgspace_data)) niftiwriter = niftiWriter(item[0] + '/procpar', magnitude_data) output_name_magnitude = self.proc_dir + '/' + self.pslabel + '_' + str( shift) + 'us_mag' niftiwriter.write(output_name_magnitude) niftiwriter = niftiWriter(item[1] + '/procpar', phase_data) output_name_phase = self.proc_dir + '/' + self.pslabel + '_' + str( shift) + 'us_ph' niftiwriter.write(output_name_phase) output_name_unwrapped = self.proc_dir + '/' + self.pslabel + '_' + str( shift) + 'us_unwrapped_ph' if float(ppr.read()['roshift']) == 0.00037: plus_pi_data = imgspace_data if float(ppr.read()['roshift']) == -0.00037: minus_pi_data = imgspace_data if float(ppr.read()['roshift']) == 0: magnitude_name_for_prelude = output_name_magnitude copyfile(item[0] + '/procpar', self.proc_dir + '/procpar') if self.unwrap_all: print('Unwrapping phasemaps ...') os.system('prelude -p '+output_name_phase+' -a '+output_name_magnitude+ \ ' -u '+output_name_unwrapped) with open(self.preproc_data, 'a') as openfile: line = str(float(ppr.read()['roshift']))+','\ +output_name_magnitude+','\ +output_name_phase+'\n' openfile.write(line) if self.preproc_from_fid: pass if self.make_fieldmap: make_fieldmap(minus_pi_data, plus_pi_data, procpar[0]) return