def compute(self): all_data = self.getData('data') xml_header = self.getData('ISMRMRDHeader') header = ismrmrd.xsd.CreateFromDocument(xml_header) enc = header.encoding[0] #Parallel imaging factor acc_factor = 1 if enc.parallelImaging: acc_factor = enc.parallelImaging.accelerationFactor.kspace_encoding_step_1 # Coil combination print "Calculating coil images and CSM" coil_images = transform.transform_kspace_to_image(np.squeeze(np.mean(all_data,0)),(1,2)) (csm,rho) = coils.calculate_csm_walsh(coil_images) csm_ss = np.sum(csm * np.conj(csm),0) csm_ss = csm_ss + 1.0*(csm_ss < np.spacing(1)).astype('float32') if acc_factor > 1: coil_data = np.squeeze(np.mean(all_data,0)) if self.getVal('Parallel Imaging Method') == 0: (unmix,gmap) = grappa.calculate_grappa_unmixing(coil_data, acc_factor,csm=csm) elif self.getVal('Parallel Imaging Method') == 1: (unmix,gmap) = sense.calculate_sense_unmixing(acc_factor,csm) else: raise Exception('Unknown parallel imaging method') recon = np.zeros((all_data.shape[-4],all_data.shape[-2],all_data.shape[-1]), dtype=np.complex64) for r in range(0,all_data.shape[-4]): recon_data = transform.transform_kspace_to_image(np.squeeze(all_data[r,:,:,:]),(1,2))*np.sqrt(acc_factor) if acc_factor > 1: recon[r,:,:] = np.sum(unmix * recon_data,0) else: recon[r,:,:] = np.sum(np.conj(csm) * recon_data,0) print "Reconstruction done" self.setData('recon', recon) if acc_factor == 1: gmap = np.ones((all_data.shape[-2],all_data.shape[-1]),dtype=np.float32) self.setData('gmap',gmap) return 0
def process(self, acq, data,*args): if self.buffer is None: # Matrix size eNx = self.enc.encodedSpace.matrixSize.x eNy = self.enc.encodedSpace.matrixSize.y eNz = self.enc.encodedSpace.matrixSize.z rNx = self.enc.reconSpace.matrixSize.x rNy = self.enc.reconSpace.matrixSize.y rNz = self.enc.reconSpace.matrixSize.z # Field of View eFOVx = self.enc.encodedSpace.fieldOfView_mm.x eFOVy = self.enc.encodedSpace.fieldOfView_mm.y eFOVz = self.enc.encodedSpace.fieldOfView_mm.z rFOVx = self.enc.reconSpace.fieldOfView_mm.x rFOVy = self.enc.reconSpace.fieldOfView_mm.y rFOVz = self.enc.reconSpace.fieldOfView_mm.z channels = acq.active_channels if data.shape[1] != rNx: raise("Error, Recon gadget expects data to be on correct matrix size in RO direction") if (rNz != 1): rasie("Error Recon Gadget only supports 2D for now") self.buffer = np.zeros((channels, rNy, rNx),dtype=np.complex64) self.samp_mask = np.zeros(self.buffer.shape[1:]) self.header_proto = ismrmrd.ImageHeader() self.header_proto.matrix_size[0] = rNx self.header_proto.matrix_size[1] = rNy self.header_proto.matrix_size[2] = rNz self.header_proto.field_of_view[0] = rFOVx self.header_proto.field_of_view[1] = rFOVy self.header_proto.field_of_view[0] = rFOVz #Now put data in buffer line_offset = self.buffer.shape[1]/2 - self.enc.encodingLimits.kspace_encoding_step_1.center self.buffer[:,acq.idx.kspace_encode_step_1+line_offset,:] = data self.samp_mask[acq.idx.kspace_encode_step_1+line_offset,:] = 1 #If last scan in buffer, do FFT and fill image header if acq.isFlagSet(ismrmrd.ACQ_LAST_IN_ENCODE_STEP1) or acq.isFlagSet(ismrmrd.ACQ_LAST_IN_SLICE): img_head = copy.deepcopy(self.header_proto) img_head.position = acq.position img_head.read_dir = acq.read_dir img_head.phase_dir = acq.phase_dir img_head.slice_dir = acq.slice_dir img_head.patient_table_position = acq.patient_table_position img_head.acquisition_time_stamp = acq.acquisition_time_stamp img_head.slice = acq.idx.slice img_head.channels = 1 scale = self.samp_mask.size/(1.0*np.sum(self.samp_mask[:])); #We have not yet calculated unmixing coefficients if self.unmix is None: self.calib_buffer.append((img_head,self.buffer.copy())) self.buffer[:] = 0 self.samp_mask[:] = 0 if len(self.calib_buffer) >= self.calib_frames: cal_data = np.zeros(self.calib_buffer[0][1].shape, dtype=np.complex64) for c in self.calib_buffer: cal_data = cal_data + c[1] mask = np.squeeze(np.sum(np.abs(cal_data),0)) mask = np.ones(mask.shape)*(np.abs(mask)>0.0) target = None #cal_data[0:8,:,:] coil_images = transform.transform_kspace_to_image(cal_data,dim=(1,2)) (csm,rho) = coils.calculate_csm_walsh(coil_images) if self.method == 'grappa': self.unmix, self.gmap = grappa.calculate_grappa_unmixing(cal_data, self.acc_factor, data_mask=mask, kernel_size=(4,5), csm=csm) elif self.method == 'sense': self.unmix, self.gmap = sense.calculate_sense_unmixing(self.acc_factor, csm) else: raise Exception('Unknown parallel imaging method: ' + str(self.method)) for c in self.calib_buffer: recon = transform.transform_kspace_to_image(c[1],dim=(1,2))*np.sqrt(scale) recon = np.squeeze(np.sum(recon * self.unmix,0)) self.put_next(c[0], recon,*args) return 0 if self.unmix is None: raise Exception("We should never reach this point without unmixing coefficients") recon = transform.transform_kspace_to_image(self.buffer,dim=(1,2))*np.sqrt(scale) recon = np.squeeze(np.sum(recon * self.unmix,0)) self.buffer[:] = 0 self.samp_mask[:] = 0 self.put_next(img_head,recon,*args) return 0
# -*- coding: utf-8 -*- #%% #Basic setup import time import numpy as np from ismrmrdtools import simulation, coils, show matrix_size = 256 csm = simulation.generate_birdcage_sensitivities(matrix_size) phan = simulation.phantom(matrix_size) coil_images = phan[np.newaxis, :, :] * csm show.imshow(abs(coil_images), tile_shape=(4, 2)) tstart = time.time() (csm_est, rho) = coils.calculate_csm_walsh(coil_images) print("Walsh coil estimation duration: {}s".format(time.time() - tstart)) combined_image = np.sum(csm_est * coil_images, axis=0) show.imshow(abs(csm_est), tile_shape=(4, 2), scale=(0, 1)) show.imshow(abs(combined_image), scale=(0, 1)) tstart = time.time() (csm_est2, rho2) = coils.calculate_csm_inati_iter(coil_images) print("Inati coil estimation duration: {}s".format(time.time() - tstart)) combined_image2 = np.sum(csm_est2 * coil_images, axis=0) show.imshow(abs(csm_est2), tile_shape=(4, 2), scale=(0, 1)) show.imshow(abs(combined_image2), scale=(0, 1))