Beispiel #1
0
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
Beispiel #2
0
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
Beispiel #4
0
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()

Beispiel #5
0
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()