def deapodization(Ns,KB,Ns_orig): xx=np.arange(1,Ns+1)-Ns/2-1 dpz=np.fft.fftshift(np.fft.ifft2(np.fft.fftshift(np.reshape(KB(xx,np.array(0)),(np.size(xx),1))*KB(xx,np.array(0))))) # assume oversampling, do not divide outside box in real space: msk = padmat(np.ones((Ns_orig,Ns_orig)),np.array((Ns,Ns)),0) msk=msk.astype(bool) dpz=dpz.real#astype(float) dpz[~msk] = 1 #keep the value outside box dpz=1/dpz #deapodization factor truncated dpz=dpz/dpz[Ns/2+1,Ns/2+1] #scaling return dpz
def init_nufft_params(sino, geom): # Function to initialize parameters associated with the forward model #inputs : sino - A list contating parameters associated with the sinogram # Ns : Number of entries in the padded sinogram along the "detector" rows # Ns_orig : Number of entries detector elements per slice # center : Center of rotation in pixels computed from the left end of the detector # angles : An array containg the angles at which the data was acquired in radians # : geom - TBD # KBLUT_LENGTH = 256 SCALING_FACTOR = 1.7 #What is this ? k_r = 3 #kernel size 2*kr+1 beta = 4 * math.pi Ns = sino['Ns'] Ns_orig = sino['Ns_orig'] ang = sino['angles'] q_grid = np.arange(1, sino['Ns'] + 1) - np.floor((sino['Ns'] + 1) / 2) - 1 sino['tt'], sino['qq'] = np.meshgrid(ang * 180 / math.pi, q_grid) # Preload the Bessel kernel (real components!) kblut, KB, KB1D, KB2D = KBlut(k_r, beta, KBLUT_LENGTH) KBnorm = np.array( np.single( np.sum( np.sum( KB2D( np.reshape(np.arange(-k_r, k_r + 1), (2 * k_r + 1, 1)), (np.arange(-k_r, k_r + 1))))))) #print KBnorm kblut = kblut / KBnorm * SCALING_FACTOR #scaling fudge factor #Normalization (density compensation factor) # Dq=KBdensity1(sino['qq'],sino['tt'],KB1,k_r,Ns)'; # polar to cartesian, centered [xi, yi] = pol2cart(sino['qq'], sino['tt'] * math.pi / 180) xi = xi + np.floor((Ns + 1) / 2) yi = yi + np.floor((Ns + 1) / 2) params = {} params['k_r'] = k_r params['deapod_filt'] = afnp.array(deapodization(Ns, KB, Ns_orig), dtype=afnp.float32) params['sino_mask'] = afnp.array(padmat( np.ones((Ns_orig, sino['qq'].shape[1])), np.array((Ns, sino['qq'].shape[1])), 0), dtype=afnp.float32) params['grid'] = [Ns, Ns] #np.array([Ns,Ns],dtype=np.int32) params['scale'] = ((KBLUT_LENGTH - 1) / k_r) params['center'] = afnp.array(sino['center']) params['Ns'] = Ns # push parameters to gpu and initalize a few in-line functions params['gxi'] = afnp.array(np.single(xi)) params['gyi'] = afnp.array(np.single(yi)) params['gxy'] = params['gxi'] + 1j * params['gyi'] params['gkblut'] = afnp.array(np.single(kblut)) params['det_grid'] = np.array( np.reshape(np.arange(0, sino['Ns']), (sino['Ns'], 1))) #####Generate Ram-Lak/ShepLogan like filter kernel######### temp_mask = np.ones(Ns) kernel = np.ones(Ns) if 'filter' in sino: temp_r = np.linspace(-1, 1, Ns) kernel = (Ns) * np.fabs(temp_r) * np.sinc(temp_r / 2) temp_pos = (1 - sino['filter']) / 2 temp_mask[0:np.int16(temp_pos * Ns)] = 0 temp_mask[np.int16((1 - temp_pos) * Ns):] = 0 params['giDq'] = afnp.array(kernel * temp_mask, dtype=afnp.complex64) temp = afnp.array((-1)**params['det_grid'], dtype=afnp.float32) temp2 = np.array((-1)**params['det_grid'], dtype=afnp.float32) temp2 = afnp.array(temp2.reshape(1, sino['Ns'])) temp3 = afnp.array( afnp.exp(-1j * 2 * params['center'] * (afnp.pi / params['Ns']) * params['det_grid']).astype(afnp.complex64)) temp4 = afnp.array( afnp.exp(1j * 2 * params['center'] * afnp.pi / params['Ns'] * params['det_grid']).astype(afnp.complex64)) params['fft2Dshift'] = afnp.array(temp * temp2, dtype=afnp.complex64) params['fftshift1D'] = lambda x: temp * x params['fftshift1D_center'] = lambda x: temp3 * x params['fftshift1Dinv_center'] = lambda x: temp4 * x ################# Back projector params ####################### xi = xi.astype(np.float32) yi = yi.astype(np.float32) # [s_per_b,b_dim_x,b_dim_y,s_in_bin,b_offset,b_loc,b_points_x,b_points_y] = gnufft.polarbin(xi,yi,params['grid'],4096*4,k_r) # params['gs_per_b']=afnp.array(s_per_b,dtype=afnp.int64) #int64 # params['gs_in_bin']=afnp.array(s_in_bin,dtype=afnp.int64) # params['gb_dim_x']= afnp.array(b_dim_x,dtype=afnp.int64) # params['gb_dim_y']= afnp.array(b_dim_y,dtype=afnp.int64) # params['gb_offset']=afnp.array(b_offset,dtype=afnp.int64) # params['gb_loc']=afnp.array(b_loc,dtype=afnp.int64) # params['gb_points_x']=afnp.array(b_points_x,dtype=afnp.float32) # params['gb_points_y']=afnp.array(b_points_y,dtype=afnp.float32) return params
### Comparing to tomopy sim = tomopy.project(obj, ang) sino = {} geom = {} sino['Ns'] = 768 #3624#im_size*2 #Sinogram size after padding sino['Ns_orig'] = im_size #size of original sinogram sino['center'] = sino_center + (sino['Ns'] / 2 - sino['Ns_orig'] / 2 ) #for padded sinogram sino['angles'] = ang params = init_nufft_params(sino, geom) ##Create a simulated object to test forward and back-projection routines x = afnp.array(padmat(obj[slice_idx], np.array([sino['Ns'], sino['Ns']]), 0), dtype=afnp.complex64) t = time.time() num_iter = 2 for i in range(1, num_iter + 1): #Ax = (math.pi/2)*sino['Ns']*forward_project(x,params) Ax = forward_project(x, params) elapsed_time = (time.time() - t) / num_iter print('Time for Forward Proj :', elapsed_time) print('Min value of real FP=%f' % (Ax.real.min())) print('Max value of real FP = %f' % (Ax.real.max())) t = time.time() for i in range(1, num_iter + 1): y = back_project(Ax, params) * sino['Ns_orig'] * num_angles
plt.figure() plt.imshow(y[num_slice/4].imag,cmap='gray') plt.colorbar() plt.title('NUFFT back-proj') plt.draw() plt.figure();plt.imshow(obj[slice_idx],cmap='gray');plt.colorbar(); plt.title('Original slice'); plt.draw(); #plt.imshow(x,cmap='gray') #####Plotting ####### #tomopy tomopy_sim_slice = np.flipud(np.fliplr(padmat(sim[:,slice_idx,:],np.array([num_angles, sino['Ns']]),0))) plt.figure();plt.imshow(tomopy_sim_slice,cmap='gray');plt.title('Tomopy projection');plt.colorbar();plt.draw(); Ax_error = np.array(Ax[num_slice/4].imag.T) - tomopy_sim_slice Ax_rmse = np.sum(np.sum((Ax_error**2)/Ax_error.size)) print('Normalized RMSE = ', Ax_rmse) plt.figure();plt.imshow(Ax[num_slice/4].imag.T,cmap='gray');plt.title('NUFFT projection');plt.colorbar();plt.draw(); plt.figure();plt.imshow(Ax_error,cmap='gray');plt.title('Difference in projection');plt.colorbar();plt.draw(); plt.show()
sino['center'] = sino_center + (sino['Ns'] / 2 - sino['Ns_orig'] / 2 ) #for padded sinogram sino['angles'] = ang sino[ 'filter'] = 1 #Paramter to control strength of FBP filter normalized to [0,1] params = init_nufft_params(sino, geom) #norm_data=afnp.array(norm_data[:40],dtype=afnp.complex64) #temp_mat=afnp.array(np.zeros((sino['Ns'],num_angles)),dtype=afnp.complex64) t = time.time() #loop over all slices for i in range(500, 551): #pad data array and move it to GPU Ax = afnp.array(padmat(norm_data[i], np.array([sino['Ns'], num_angles]), 0), dtype=afnp.complex64) # Ax = padmat_v2(norm_data[i],np.array([sino['Ns'],num_angles]),0,temp_mat) # temp_mat=temp_mat*0 #filtered back-projection y = back_project(Ax, params) elapsed_time = (time.time() - t) print('Time for Back-proj of all slices :', elapsed_time) plt.imshow(np.abs(y), cmap='gray') plt.colorbar() plt.title('Reconstructed slice') plt.show()