def setup_Lipschitz_constant(self): if self.RecToolsIR is not None: return # set parameters and initiate a TomoRec class object self.Rectools = RecToolsIR(DetectorsDimH = self.DetectorsDimH, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV = None, # DetectorsDimV # detector dimension (vertical) for 3D case only AnglesVec = self.angles, # array of angles in radians ObjSize = self.vol_shape[0] , # a scalar to define reconstructed object dimensions datafidelity=self.datafidelity,# data fidelity, choose LS, PWLS (wip), GH (wip), Student (wip) nonnegativity=self.nonnegativity, # enable nonnegativity constraint (set to 'on') OS_number = self.ordersubsets, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance = 1e-9, # tolerance to stop outer iterations earlier device='gpu') if (self.parameters['converg_const'] == 'power'): self.Lipschitz_const = self.Rectools.powermethod() # calculate Lipschitz constant else: self.Lipschitz_const = self.parameters['converg_const'] return
Qtools = QualityTools(phantom[128,:,:]*255, recFBP[128,:,:]*235) win = np.array([gaussian(11, 1.5)]) win2d = win * (win.T) ssim_fbp = Qtools.ssim(win2d) print("Mean SSIM for FBP is {}".format(ssim_fbp[0])) #%% print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print ("Reconstructing with ADMM method using TomoRec software") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") # initialise TomoRec ITERATIVE reconstruction class ONCE from tomorec.methodsIR import RecToolsIR RectoolsIR = RecToolsIR(DetectorsDimH = Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV = Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only AnglesVec = proj_angles, # array of angles in radians ObjSize = N_size, # a scalar to define reconstructed object dimensions datafidelity='LS',# data fidelity, choose LS, PWLS (wip), GH (wip), Student (wip) nonnegativity='ENABLE', # enable nonnegativity constraint (set to 'ENABLE') OS_number = None, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance = 1e-06, # tolerance to stop outer -ADMM iterations earlier device='gpu') #%% print ("Reconstructing with ADMM method using SB-TV penalty") RecADMM_reg_sbtv = RectoolsIR.ADMM(projdata_norm, rho_const = 2000.0, \ iterationsADMM = 25, \ regularisation = 'SB_TV', \ regularisation_parameter = optimReg_sbtv,\ regularisation_iterations = 50) sliceSel = int(0.5*N_size) max_val = 1
Qtools = QualityTools(phantom_tm, recNumerical) RMSE = Qtools.rmse() print("Root Mean Square Error is {}".format(RMSE)) #%% print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print("Reconstructing with FISTA-OS method using TomoRec") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") # initialise TomoRec ITERATIVE reconstruction class ONCE from tomorec.methodsIR import RecToolsIR RectoolsIR = RecToolsIR( DetectorsDimH=Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only AnglesVec=angles_rad, # array of angles in radians ObjSize=N_size, # a scalar to define reconstructed object dimensions datafidelity= 'LS', # data fidelity, choose LS, PWLS (wip), GH (wip), Student (wip) nonnegativity='on', # enable nonnegativity constraint (set to 'on') OS_number= 12, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance=1e-07, # tolerance to stop outer iterations earlier device='gpu') lc = RectoolsIR.powermethod() # calculate Lipschitz constant #%% # Run FISTA reconstrucion algorithm without regularisation RecFISTA = RectoolsIR.FISTA(projData3D_analyt_noisy, iterationsFISTA=5, lipschitz_const=lc) # Run FISTA reconstrucion algorithm with 3D regularisation
plt.colorbar(ticks=[0, 150, 250], orientation='vertical') plt.title('{}' '{}'.format('Analytical noisy sinogram with artifacts', model)) #%% print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print("Reconstructing with FISTA method (ASTRA used for projection)") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") from tomorec.methodsIR import RecToolsIR from ccpi.filters.regularisers import PatchSelect # set parameters and initiate a class object Rectools = RecToolsIR( DetectorsDimH=P, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= None, # DetectorsDimV # detector dimension (vertical) for 3D case only AnglesVec=angles_rad, # array of angles in radians ObjSize=N_size, # a scalar to define reconstructed object dimensions datafidelity= 'LS', # data fidelity, choose LS, PWLS (wip), GH (wip), Student (wip) OS_number= None, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance=1e-06, # tolerance to stop outer iterations earlier device='gpu') lc = Rectools.powermethod( ) # calculate Lipschitz constant (run once to initilise) from tomorec.methodsDIR import RecToolsDIR RectoolsDIR = RecToolsDIR( DetectorsDimH=P, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= None, # DetectorsDimV # detector dimension (vertical) for 3D case only AnglesVec=angles_rad, # array of angles in radians
plt.figure() #plt.imshow(FBPrec[500:1500,500:1500], vmin=0, vmax=1, cmap="gray") plt.imshow(FBPrec, vmin=0, vmax=1, cmap="gray") plt.title('FBP reconstruction') #%% from tomorec.methodsIR import RecToolsIR # set parameters and initiate a class object Rectools = RecToolsIR( DetectorsDimH=np.size( det_y_crop), # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= None, # DetectorsDimV # detector dimension (vertical) for 3D case only AnglesVec=angles_rad, # array of angles in radians ObjSize=N_size, # a scalar to define reconstructed object dimensions datafidelity= 'PWLS', # data fidelity, choose LS, PWLS, GH (wip), Student (wip) OS_number= None, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance=1e-08, # tolerance to stop outer iterations earlier device='gpu') # Run CGLS reconstrucion algorithm RecCGLS = Rectools.CGLS(np.transpose(data_norm[det_y_crop, :, 0]), iterations=7) plt.figure() plt.imshow(RecCGLS, vmin=0, vmax=0.3, cmap="gray") plt.title('CGLS reconstruction') plt.show()
plt.figure() plt.imshow(abs(FBPrec_ideal - FBPrec_error), vmin=0, vmax=1, cmap="gray") plt.colorbar(ticks=[0, 0.5, 1], orientation='vertical') plt.title('FBP reconsrtuction differences') #%% # initialise TomoRec ITERATIVE reconstruction class ONCE from tomorec.methodsIR import RecToolsIR RectoolsIR = RecToolsIR( DetectorsDimH=P, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= None, # DetectorsDimV # detector dimension (vertical) for 3D case only AnglesVec=angles_rad, # array of angles in radians ObjSize=N_size, # a scalar to define reconstructed object dimensions datafidelity= 'LS', # data fidelity, choose LS, PWLS (wip), GH (wip), Student (wip) nonnegativity='ENABLE', # enable nonnegativity constraint (set to 'ENABLE') OS_number= None, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance=1e-06, # tolerance to stop outer iterations earlier device='gpu') #%% print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print("Reconstructing analytical sinogram using SIRT (TomoRec)...") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") iterationsSIRT = 250 SIRTrec_ideal = RectoolsIR.SIRT(sino_an, iterationsSIRT) # ideal reconstruction SIRTrec_error = RectoolsIR.SIRT(noisy_zing_stripe, iterationsSIRT) # error reconstruction
class FistaRecon(BaseRecon, GpuPlugin): """ A Plugin to reconstruct data by using FISTA iterative algorithm implemented \ in TomoRec package. Dependencies on TomoRec, ASTRA toolbox and CCPi RGL toolkit: \ https://github.com/vais-ral/CCPi-Regularisation-Toolkit. :param iterationsFISTA: Number of FISTA iterations. Default: 20. :param datafidelity: Data fidelity, Least Squares only at the moment. Default: 'LS'. :param nonnegativity: Nonnegativity constraint, choose on or None. Default: 'ENABLE'. :param ordersubsets: The number of ordered-subsets to accelerate reconstruction. Default: 6. :param converg_const: Lipschitz constant, can be set to a value. Default: 'power'. :param regularisation: To regularise choose ROF_TV, FGP_TV, SB_TV, LLT_ROF,\ NDF, Diff4th. Default: 'FGP_TV'. :param regularisation_parameter: Regularisation (smoothing) value, higher \ the value stronger the smoothing effect. Default: 0.001. :param regularisation_iterations: The number of regularisation iterations. Default: 170. :param time_marching_parameter: Time marching parameter, relevant for \ (ROF_TV, LLT_ROF, NDF, Diff4th) penalties. Default: 0.0025. :param edge_param: Edge (noise) related parameter, relevant for NDF and Diff4th. Default: 0.01. :param regularisation_parameter2: Regularisation (smoothing) value for LLT_ROF method. Default: 0.005. :param NDF_penalty: NDF specific penalty type Huber, Perona, Tukey. Default: 'Huber'. """ def __init__(self): super(FistaRecon, self).__init__("FistaRecon") def _shift(self, sinogram, centre_of_rotation): centre_of_rotation_shift = (sinogram.shape[0]/2) - \ float(centre_of_rotation) return ndimage.interpolation.shift(sinogram, centre_of_rotation_shift) def pre_process(self): # extract given parameters self.iterationsFISTA = self.parameters['iterationsFISTA'] self.datafidelity = self.parameters['datafidelity'] self.nonnegativity = self.parameters['nonnegativity'] self.ordersubsets = self.parameters['ordersubsets'] self.converg_const = self.parameters['converg_const'] self.regularisation = self.parameters['regularisation'] self.regularisation_parameter = self.parameters['regularisation_parameter'] self.regularisation_parameter2 = self.parameters['regularisation_parameter2'] self.time_marching_parameter = self.parameters['time_marching_parameter'] self.edge_param = self.parameters['edge_param'] self.NDF_penalty = self.parameters['NDF_penalty'] self.RecToolsIR = None if (self.ordersubsets > 1): self.regularisation_iterations = (int)(self.parameters['regularisation_iterations']/self.ordersubsets) + 1 else: self.regularisation_iterations = self.parameters['regularisation_iterations'] def process_frames(self, data): centre_of_rotations, angles, self.vol_shape, init = self.get_frame_params() sino = data[0].astype(np.float32) anglesTot, self.DetectorsDimH = np.shape(sino) self.angles = np.deg2rad(angles.astype(np.float32)) # check if the reconstruction class has been initialised and calculate # Lipschitz constant if not given explicitly self.setup_Lipschitz_constant() # Run FISTA reconstrucion algorithm here recon = self.Rectools.FISTA(sino,\ iterationsFISTA = self.iterationsFISTA,\ regularisation = self.regularisation,\ regularisation_parameter = self.regularisation_parameter,\ regularisation_iterations = self.regularisation_iterations,\ regularisation_parameter2 = self.regularisation_parameter2,\ time_marching_parameter = self.time_marching_parameter,\ NDF_penalty = self.NDF_penalty,\ tolerance_regul = 1e-10,\ edge_param = self.edge_param,\ lipschitz_const = self.Lipschitz_const) return recon def setup_Lipschitz_constant(self): if self.RecToolsIR is not None: return # set parameters and initiate a TomoRec class object self.Rectools = RecToolsIR(DetectorsDimH = self.DetectorsDimH, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV = None, # DetectorsDimV # detector dimension (vertical) for 3D case only AnglesVec = self.angles, # array of angles in radians ObjSize = self.vol_shape[0] , # a scalar to define reconstructed object dimensions datafidelity=self.datafidelity,# data fidelity, choose LS, PWLS (wip), GH (wip), Student (wip) nonnegativity=self.nonnegativity, # enable nonnegativity constraint (set to 'on') OS_number = self.ordersubsets, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance = 1e-9, # tolerance to stop outer iterations earlier device='gpu') if (self.parameters['converg_const'] == 'power'): self.Lipschitz_const = self.Rectools.powermethod() # calculate Lipschitz constant else: self.Lipschitz_const = self.parameters['converg_const'] return def get_max_frames(self): return 'single' def get_citation_information(self): cite_info1 = CitationInformation() cite_info1.name = 'citation1' cite_info1.description = \ ("First-order optimisation algorithm for linear inverse problems.") cite_info1.bibtex = \ ("@article{beck2009,\n" + "title={A fast iterative shrinkage-thresholding algorithm for linear inverse problems},\n" + "author={Amir and Beck, Mark and Teboulle},\n" + "journal={SIAM Journal on Imaging Sciences},\n" + "volume={2},\n" + "number={1},\n" + "pages={183--202},\n" + "year={2009},\n" + "publisher={SIAM}\n" + "}") cite_info1.endnote = \ ("%0 Journal Article\n" + "%T A fast iterative shrinkage-thresholding algorithm for linear inverse problems\n" + "%A Beck, Amir\n" + "%A Teboulle, Mark\n" + "%J SIAM Journal on Imaging Sciences\n" + "%V 2\n" + "%N 1\n" + "%P 183--202\n" + "%@ --\n" + "%D 2009\n" + "%I SIAM\n") cite_info1.doi = "doi: " return cite_info1
print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") from tomorec.methodsIR import RecToolsIR N_size = 950 detectHoriz, anglesNum, timeframe_no = np.shape(data_norm) FISTA_TV_timeframes = np.zeros((N_size, N_size, timeframe_no), dtype='float32') for i in range(0, timeframe_no): # set parameters and initiate a class object Rectools = RecToolsIR( DetectorsDimH= detectHoriz, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= None, # DetectorsDimV # detector dimension (vertical) for 3D case only AnglesVec=angles_rad[i, :], # array of angles in radians ObjSize=N_size, # a scalar to define reconstructed object dimensions datafidelity= 'LS', # data fidelity, choose LS, PWLS, GH (wip), Student (wip) OS_number= 12, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance=1e-08, # tolerance to stop outer iterations earlier device='gpu') lc = Rectools.powermethod( ) # calculate Lipschitz constant (run once to initilise) FISTA_TV_timeframes[:,:,i] = Rectools.FISTA(np.transpose(data_norm[:,:,i]), \ iterationsFISTA = 12, \ regularisation = 'FGP_TV', \ regularisation_parameter = 0.0025,\ regularisation_iterations = 200,\
AnglesVec = angles_rad, # array of angles in radians ObjSize = N_size, # a scalar to define reconstructed object dimensions device='gpu') FBPrec = RectoolsDIR.FBP(np.transpose(data_norm[:,:,slice_to_recon])) plt.figure() plt.imshow(FBPrec[150:550,150:550], vmin=0, vmax=0.005, cmap="gray") plt.title('FBP reconstruction') from tomorec.methodsIR import RecToolsIR # set parameters and initiate a class object Rectools = RecToolsIR(DetectorsDimH = detectorHoriz, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV = None, # DetectorsDimV # detector dimension (vertical) for 3D case only AnglesVec = angles_rad, # array of angles in radians ObjSize = N_size, # a scalar to define reconstructed object dimensions datafidelity='PWLS',# data fidelity, choose LS, PWLS, GH (wip), Student (wip) OS_number = 12, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance = 1e-08, # tolerance to stop outer iterations earlier device='gpu') lc = Rectools.powermethod(np.transpose(dataRaw[:,:,slice_to_recon])) # calculate Lipschitz constant (run once to initilise) RecFISTA_os_pwls = Rectools.FISTA(np.transpose(data_norm[:,:,slice_to_recon]), \ np.transpose(dataRaw[:,:,slice_to_recon]), \ iterationsFISTA = 15, \ lipschitz_const = lc) fig = plt.figure() plt.imshow(RecFISTA_os_pwls[150:550,150:550], vmin=0, vmax=0.003, cmap="gray") #plt.imshow(RecFISTA_os_pwls, vmin=0, vmax=0.004, cmap="gray") plt.title('FISTA PWLS-OS reconstruction')
for i in range(0,np.size(FBPrec,0)): tiff = TIFF.open('Dendr_FBP'+'_'+str(i)+'.tiff', mode='w') tiff.write_image(np.uint16(FBPrec[i,:,:]*multiplier)) tiff.close() """ #%% print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print ("Reconstructing with ADMM method using TomoRec software") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") # initialise TomoRec ITERATIVE reconstruction class ONCE from tomorec.methodsIR import RecToolsIR RectoolsIR = RecToolsIR(DetectorsDimH = np.size(det_y_crop), # DetectorsDimH # detector dimension (horizontal) DetectorsDimV = 100, # DetectorsDimV # detector dimension (vertical) for 3D case only AnglesVec = angles_rad, # array of angles in radians ObjSize = N_size, # a scalar to define reconstructed object dimensions datafidelity='LS',# data fidelity, choose LS, PWLS, GH (wip), Students t (wip) nonnegativity='ENABLE', # enable nonnegativity constraint (set to 'ENABLE') OS_number = None, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance = 0.0, # tolerance to stop inner (regularisation) iterations earlier device='gpu') #%% print ("Reconstructing with ADMM method using SB-TV penalty") RecADMM_reg_sbtv = RectoolsIR.ADMM(data_norm[0:100,:,det_y_crop], rho_const = 2000.0, \ iterationsADMM = 15, \ regularisation = 'SB_TV', \ regularisation_parameter = 0.00085,\ regularisation_iterations = 50) sliceSel = 50 max_val = 0.003