def process_frames(self, data): centre_of_rotations, angles, self.vol_shape, init = self.get_frame_params() self.anglesRAD = np.deg2rad(angles.astype(np.float32)) self.centre_of_rotations = centre_of_rotations projdata3D = data[0].astype(np.float32) dim_tuple = np.shape(projdata3D) self.Horiz_det = dim_tuple[self.det_dimX_ind] #print(np.shape(projdata3D)) projdata3D =np.swapaxes(projdata3D,0,1) # WIP for PWLS fidelity # rawdata3D = data[1].astype(np.float32) # rawdata3D =np.swapaxes(rawdata3D,0,1)/np.max(np.float32(rawdata3D)) self._data_.update({'projection_norm_data' : projdata3D}) # set parameters and initiate a TomoBar class object self.Rectools = RecToolsIR(DetectorsDimH = self.Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV = self.Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset = 0.0, # Center of Rotation (CoR) scalar (for 3D case only) AnglesVec = self.anglesRAD, # array of angles in radians ObjSize = self.output_size, # a scalar to define the reconstructed object dimensions datafidelity=self.parameters['data_fidelity'],# data fidelity, choose LS device_projector='gpu') # Run FISTA reconstrucion algorithm here recon = self.Rectools.FISTA(self._data_, self._algorithm_, self._regularisation_) recon = np.swapaxes(recon,0,1) return recon
def process_frames(self, data): cor, angles, self.vol_shape, init = self.get_frame_params() sinogram = data[0].astype(np.float32) anglesTot, self.DetectorsDimH = np.shape(sinogram) half_det_width = 0.5*self.DetectorsDimH cor_astra = half_det_width - cor self.anglesRAD = np.deg2rad(angles.astype(np.float32)) self._data_.update({'projection_norm_data' : sinogram}) # if one selects PWLS or SWLS models then raw data is also required (2 inputs) if ((self.parameters['data_fidelity'] == 'PWLS') or (self.parameters['data_fidelity'] == 'SWLS')): rawdata = data[1].astype(np.float32) rawdata /= np.max(rawdata) self._data_.update({'projection_raw_data' : rawdata}) self._data_.update({'beta_SWLS' : self.parameters['data_beta_SWLS']*np.ones(self.DetectorsDimH)}) # set parameters and initiate the ToMoBAR class object self.Rectools = RecToolsIR(DetectorsDimH = self.DetectorsDimH, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV = None, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset = cor_astra.item() - 0.5, # The center of rotation (CoR) scalar or a vector AnglesVec = self.anglesRAD, # the vector of angles in radians ObjSize = self.vol_shape[0] , # a scalar to define the reconstructed object dimensions datafidelity=self.parameters['data_fidelity'],# data fidelity, choose LS, PWLS, SWLS device_projector='gpu') # Run FISTA reconstrucion algorithm here recon = self.Rectools.FISTA(self._data_, self._algorithm_, self._regularisation_) return recon
def process_frames(self, data): centre_of_rotations, angles, self.vol_shape, init = self.get_frame_params( ) sinogram = data[0].astype(np.float32) anglesTot, self.DetectorsDimH = np.shape(sinogram) self.anglesRAD = np.deg2rad(angles.astype(np.float32)) self._data_.update({'projection_norm_data': sinogram}) """ # if one selects PWLS model and provides raw input data if (self.parameters['data_fidelity'] == 'PWLS'): rawdata = data[1].astype(np.float32) rawdata /= np.max(rawdata) self._data_.update({'projection_raw_data' : rawdata}) """ # set parameters and initiate the ToMoBAR class object self.Rectools = RecToolsIR( DetectorsDimH=self. DetectorsDimH, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= None, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset= None, # Center of Rotation (CoR) scalar (for 3D case only) AnglesVec=self.anglesRAD, # array of angles in radians ObjSize=self.vol_shape[ 0], # a scalar to define the reconstructed object dimensions datafidelity=self. parameters['data_fidelity'], # data fidelity, choose LS, PWLS device_projector='gpu') # Run FISTA reconstrucion algorithm here recon = self.Rectools.FISTA(self._data_, self._algorithm_, self._regularisation_) return recon
def setup_Lipschitz_constant(self): if self.RecToolsIR is not None: return # set parameters and initiate a TomoBar class object self.Rectools = RecToolsIR( DetectorsDimH=self. Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV=self. Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset= 0.0, # Center of Rotation (CoR) scalar (for 3D case only) AnglesVec=self.anglesRAD, # array of angles in radians ObjSize=self. output_size, # a scalar to define the reconstructed object dimensions datafidelity=self.datafidelity, # data fidelity, choose LS nonnegativity=self. nonnegativity, # enable nonnegativity constraint (set to 'on') OS_number=self. ordersubsets, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance=self. tolerance, # 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 process_frames(self, data): cor, angles, self.vol_shape, init = self.get_frame_params() self.anglesRAD = np.deg2rad(angles.astype(np.float32)) projdata3D = data[0].astype(np.float32) dim_tuple = np.shape(projdata3D) self.Horiz_det = dim_tuple[self.det_dimX_ind] half_det_width = 0.5 * self.Horiz_det cor_astra = half_det_width - cor[0] projdata3D[projdata3D > 10**15] = 0.0 projdata3D = np.swapaxes(projdata3D, 0, 1) #print(f"Shape of projdata3D is {np.shape(projdata3D)}") self._data_.update({'projection_norm_data': projdata3D}) # if one selects PWLS or SWLS models then raw data is also required (2 inputs) if ((self.parameters['data_fidelity'] == 'PWLS') or (self.parameters['data_fidelity'] == 'SWLS')): rawdata3D = data[1].astype(np.float32) rawdata3D[rawdata3D > 10**15] = 0.0 rawdata3D = np.swapaxes(rawdata3D, 0, 1) / np.max( np.float32(rawdata3D)) #print(f"Shape of rawdata3D is {np.shape(rawdata3D)}") self._data_.update({'projection_raw_data': rawdata3D}) self._data_.update({ 'beta_SWLS': self.parameters['data_beta_SWLS'] * np.ones(self.Horiz_det) }) # set parameters and initiate a TomoBar class object self.Rectools = RecToolsIR( DetectorsDimH=self. Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV=self. Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset=cor_astra.item() - 0.5, # The center of rotation (CoR) scalar or a vector AnglesVec=self.anglesRAD, # the vector of angles in radians ObjSize=self. output_size, # a scalar to define the reconstructed object dimensions datafidelity=self.parameters[ 'data_fidelity'], # data fidelity, choose LS, PWLS, SWLS device_projector='gpu') # Run FISTA reconstrucion algorithm here recon = self.Rectools.FISTA(self._data_, self._algorithm_, self._regularisation_) recon = np.swapaxes(recon, 0, 1) return recon
class TomobarRecon3d(BaseRecon, MultiThreadedPlugin): """ A Plugin to reconstruct full-field tomographic projection data using state-of-the-art regularised iterative algorithms from \ the ToMoBAR package. ToMoBAR includes FISTA and ADMM iterative methods and depends on the ASTRA toolbox and the CCPi RGL toolkit: \ https://github.com/vais-ral/CCPi-Regularisation-Toolkit. :param output_size: The dimension of the reconstructed volume (only X-Y dimension). Default: 'auto'. :param iterations: Number of outer iterations for FISTA method. Default: 20. :param datafidelity: Data fidelity, Least Squares (LS) or PWLS. Default: 'LS'. :param nonnegativity: Nonnegativity constraint, choose Enable 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 scalar value or automatic calculation using power methods. Default: 'power'. :param regularisation: To regularise choose methods ROF_TV, FGP_TV, SB_TV, LLT_ROF,\ NDF, Diff4th. Default: 'ROF_TV'. :param regularisation_parameter: Regularisation (smoothing) value, higher \ the value stronger the smoothing effect. Default: 0.0001. :param regularisation_iterations: The number of regularisation iterations. Default: 400. :param time_marching_parameter: Time marching parameter, relevant for \ (ROF_TV, LLT_ROF, NDF, Diff4th) penalties. Default: 0.002. :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'. :param tolerance: Tolerance to stop outer iterations earlier. Default: 1e-9. :param ring_variable: Regularisation variable for ring removal. Default: 0.0. :param ring_accelerator: Acceleration constant for ring removal (use with care). Default: 50.0. """ def __init__(self): super(TomobarRecon3d, self).__init__("TomobarRecon3d") def _get_output_size(self, in_data): sizeX = self.parameters['output_size'] shape = in_data.get_shape() if sizeX == 'auto': detX = in_data.get_data_dimension_by_axis_label('detector_x') sizeX = shape[detX] detY = in_data.get_data_dimension_by_axis_label('detector_y') sizeY = shape[detY] return (sizeX, sizeY) def setup(self): in_dataset, out_dataset = self.get_datasets() # reduce the data as per data_subset parameter self.preview_flag = \ self.set_preview(in_dataset[0], self.parameters['preview']) axis_labels = in_dataset[0].data_info.get('axis_labels')[0] dim_volX, dim_volY, dim_volZ = \ self.map_volume_dimensions(in_dataset[0]) axis_labels = { in_dataset[0]: [ str(dim_volX) + '.voxel_x.voxels', str(dim_volY) + '.voxel_y.voxels', str(dim_volZ) + '.voxel_z.voxels' ] } # specify reconstructed volume dimensions (self.output_size, self.Vert_det) = self._get_output_size(in_dataset[0]) shape = [0] * len(in_dataset[0].get_shape()) shape[0] = self.output_size shape[1] = self.Vert_det shape[2] = self.output_size # if there are only 3 dimensions then add a fourth for slicing if len(shape) == 3: axis_labels = [0] * 4 axis_labels[dim_volX] = 'voxel_x.voxels' axis_labels[dim_volY] = 'voxel_y.voxels' axis_labels[dim_volZ] = 'voxel_z.voxels' axis_labels[3] = 'scan.number' shape.append(1) if self.parameters['vol_shape'] == 'fixed': shape[dim_volX] = shape[dim_volZ] else: shape[dim_volX] = self.parameters['vol_shape'] shape[dim_volZ] = self.parameters['vol_shape'] if 'resolution' in self.parameters.keys(): shape[dim_volX] /= self.parameters['resolution'] shape[dim_volZ] /= self.parameters['resolution'] out_dataset[0].create_dataset(axis_labels=axis_labels, shape=tuple(shape)) out_dataset[0].add_volume_patterns(dim_volX, dim_volY, dim_volZ) ndims = range(len(shape)) core_dims = (dim_volX, dim_volY, dim_volZ) slice_dims = tuple(set(ndims).difference(set(core_dims))) out_dataset[0].add_pattern('VOLUME_3D', core_dims=core_dims, slice_dims=slice_dims) # set information relating to the plugin data in_pData, out_pData = self.get_plugin_datasets() dim = in_dataset[0].get_data_dimension_by_axis_label('rotation_angle') nSlices = in_dataset[0].get_shape()[dim] in_pData[0].plugin_data_setup('PROJECTION', nSlices, slice_axis='rotation_angle') # in_pData[1].plugin_data_setup('PROJECTION', nSlices) # (for PWLS) # set pattern_name and nframes to process for all datasets out_pData[0].plugin_data_setup('VOLUME_3D', 'single') def pre_process(self): # extract given parameters self.iterationsFISTA = self.parameters['iterations'] 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.ring_variable = self.parameters['ring_variable'] self.ring_accelerator = self.parameters['ring_accelerator'] self.time_marching_parameter = self.parameters[ 'time_marching_parameter'] self.edge_param = self.parameters['edge_param'] self.NDF_penalty = self.parameters['NDF_penalty'] self.tolerance = self.parameters['tolerance'] 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'] in_pData = self.get_plugin_in_datasets() self.det_dimX_ind = in_pData[0].get_data_dimension_by_axis_label( 'detector_x') self.det_dimY_ind = in_pData[0].get_data_dimension_by_axis_label( 'detector_y') def process_frames(self, data): centre_of_rotations, angles, self.vol_shape, init = self.get_frame_params( ) self.anglesRAD = np.deg2rad(angles.astype(np.float32)) self.centre_of_rotations = centre_of_rotations projdata3D = data[0].astype(np.float32) dim_tuple = np.shape(projdata3D) self.Horiz_det = dim_tuple[self.det_dimX_ind] #print(np.shape(projdata3D)) projdata3D = np.swapaxes(projdata3D, 0, 1) # WIP for PWLS fidelity # rawdata3D = data[1].astype(np.float32) # rawdata3D =np.swapaxes(rawdata3D,0,1)/np.max(np.float32(rawdata3D)) # 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(projdata3D,\ 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,\ lambdaR_L1 = self.ring_variable,\ alpha_ring = self.ring_accelerator,\ NDF_penalty = self.NDF_penalty,\ tolerance_regul = 0.0,\ edge_param = self.edge_param,\ lipschitz_const = self.Lipschitz_const) recon = np.swapaxes(recon, 0, 1) # temporal fix! return recon def setup_Lipschitz_constant(self): if self.RecToolsIR is not None: return # set parameters and initiate a TomoBar class object self.Rectools = RecToolsIR( DetectorsDimH=self. Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV=self. Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset= 0.0, # Center of Rotation (CoR) scalar (for 3D case only) AnglesVec=self.anglesRAD, # array of angles in radians ObjSize=self. output_size, # a scalar to define the reconstructed object dimensions datafidelity=self.datafidelity, # data fidelity, choose LS nonnegativity=self. nonnegativity, # enable nonnegativity constraint (set to 'on') OS_number=self. ordersubsets, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance=self. tolerance, # 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 nInput_datasets(self): return 1 def nOutput_datasets(self): return 1 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
FBPrec = RectoolsDIR.FBP(data_norm[:,det_y_crop]) 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 tomobar.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 CenterRotOffset = None, # Center of Rotation (CoR) scalar (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) nonnegativity='ENABLE', # enable nonnegativity constraint (set to 'ENABLE') 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(data_norm[:,det_y_crop], iterations = 7) plt.figure() plt.imshow(RecCGLS, vmin=0, vmax=0.3, cmap="gray") plt.title('CGLS reconstruction') plt.show() #%% # Initialise FISTA-type PWLS reconstruction (run once)
class TomobarReconCpu(BaseRecon, CpuPlugin): """ A Plugin to reconstruct full-field tomographic projection data using state-of-the-art regularised iterative algorithms from \ the ToMoBAR package. ToMoBAR includes FISTA and ADMM iterative methods and depends on the ASTRA toolbox and the CCPi RGL toolkit: \ https://github.com/vais-ral/CCPi-Regularisation-Toolkit. :param output_size: Number of rows and columns in the \ reconstruction. Default: 'auto'. :param data_fidelity: Data fidelity, Least Squares only at the moment. Default: 'LS'. :param data_Huber_thresh: Threshold parameter for __Huber__ data fidelity . Default: None. :param data_any_rings: a parameter to suppress various artifacts including rings and streaks. Default: None. :param data_any_rings_winsizes: half window sizes to collect background information [detector, angles, num of projections]. Default: (9,7,0). :param data_any_rings_power: a power parameter for Huber model. Default: 1.5. :param data_full_ring_GH: Regularisation variable for full constant ring removal (GH model). Default: None. :param data_full_ring_accelerator_GH: Acceleration constant for GH ring removal. Default: 10.0. :param algorithm_iterations: Number of outer iterations for FISTA (default) or ADMM methods. Default: 20. :param algorithm_verbose: print iterations number and other messages ('off' by default). Default: 'off'. :param algorithm_ordersubsets: The number of ordered-subsets to accelerate reconstruction. Default: 6. :param algorithm_nonnegativity: ENABLE or DISABLE nonnegativity constraint. Default: 'ENABLE'. :param regularisation_method: To regularise choose methods ROF_TV, FGP_TV, PD_TV, SB_TV, LLT_ROF,\ NDF, TGV, NLTV, Diff4th. Default: 'FGP_TV'. :param regularisation_parameter: Regularisation (smoothing) value, higher \ the value stronger the smoothing effect. Default: 0.00001. :param regularisation_iterations: The number of regularisation iterations. Default: 80. :param regularisation_device: The number of regularisation iterations. Default: 'cpu'. :param regularisation_PD_lip: Primal-dual parameter for convergence. Default: 8. :param regularisation_methodTV: 0/1 - TV specific isotropic/anisotropic choice. Default: 0. :param regularisation_timestep: Time marching parameter, relevant for \ (ROF_TV, LLT_ROF, NDF, Diff4th) penalties. Default: 0.003. :param regularisation_edge_thresh: 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 regularisation_NDF_penalty: NDF specific penalty type Huber, Perona, Tukey. Default: 'Huber'. """ def __init__(self): super(TomobarReconCpu, self).__init__("TomobarReconCpu") def _shift(self, sinogram, centre_of_rotation): centre_of_rotation_shift = (sinogram.shape[0]/2) - centre_of_rotation result = ndimage.interpolation.shift(sinogram, (centre_of_rotation_shift, 0)) return result def pre_process(self): # extract given parameters into dictionaries suitable for ToMoBAR input self._data_ = {'OS_number' : self.parameters['algorithm_ordersubsets'], 'huber_threshold' : self.parameters['data_Huber_thresh'], 'ring_weights_threshold' : self.parameters['data_any_rings'], 'ring_tuple_halfsizes' : self.parameters['data_any_rings_winsizes'], 'ring_huber_power' : self.parameters['data_any_rings_power'], 'ringGH_lambda' : self.parameters['data_full_ring_GH'], 'ringGH_accelerate' : self.parameters['data_full_ring_accelerator_GH']} self._algorithm_ = {'iterations' : self.parameters['algorithm_iterations'], 'nonnegativity' : self.parameters['algorithm_nonnegativity'], 'verbose' : self.parameters['algorithm_verbose']} self._regularisation_ = {'method' : self.parameters['regularisation_method'], 'regul_param' : self.parameters['regularisation_parameter'], 'iterations' : self.parameters['regularisation_iterations'], 'device_regulariser' : self.parameters['regularisation_device'], 'edge_threhsold' : self.parameters['regularisation_edge_thresh'], 'time_marching_step' : self.parameters['regularisation_timestep'], 'regul_param2' : self.parameters['regularisation_parameter2'], 'PD_LipschitzConstant' : self.parameters['regularisation_PD_lip'], 'NDF_penalty' : self.parameters['regularisation_NDF_penalty'], 'methodTV' : self.parameters['regularisation_methodTV']} def process_frames(self, data): centre_of_rotations, angles, self.vol_shape, init = self.get_frame_params() sinogram = data[0].astype(np.float32) anglesTot, self.DetectorsDimH = np.shape(sinogram) self.anglesRAD = np.deg2rad(angles.astype(np.float32)) self._data_.update({'projection_norm_data' : sinogram}) # set parameters and initiate the ToMoBAR class object self.Rectools = RecToolsIR(DetectorsDimH = self.DetectorsDimH, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV = None, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset = None, # Center of Rotation (CoR) scalar (for 3D case only) AnglesVec = self.anglesRAD, # array of angles in radians ObjSize = self.vol_shape[0] , # a scalar to define the reconstructed object dimensions datafidelity=self.parameters['data_fidelity'],# data fidelity, choose LS, PWLS device_projector='cpu') # Run FISTA reconstrucion algorithm here recon = self.Rectools.FISTA(self._data_, self._algorithm_, self._regularisation_) return recon 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
class TomobarRecon3d(BaseRecon, GpuPlugin): """ A Plugin to reconstruct full-field tomographic projection data using state-of-the-art regularised iterative algorithms from \ the ToMoBAR package. ToMoBAR includes FISTA and ADMM iterative methods and depends on the ASTRA toolbox and the CCPi RGL toolkit: \ https://github.com/vais-ral/CCPi-Regularisation-Toolkit. :param output_size: The dimension of the reconstructed volume (only X-Y dimension). Default: 'auto'. :param padding: The amount of pixels to pad each slab of the cropped projection data. Default: 17. :param data_fidelity: Data fidelity, choose LS, PWLS, SWLS or KL. Default: 'LS'. :param data_Huber_thresh: Threshold parameter for __Huber__ data fidelity . Default: None. :param data_beta_SWLS: A parameter for stripe-weighted model. Default: 0.1. :param data_full_ring_GH: Regularisation variable for full constant ring removal (GH model). Default: None. :param data_full_ring_accelerator_GH: Acceleration constant for GH ring removal. Default: 10.0. :param algorithm_iterations: Number of outer iterations for FISTA (default) or ADMM methods. Default: 20. :param algorithm_verbose: print iterations number and other messages ('off' by default). Default: 'off'. :param algorithm_mask: set to 1.0 to enable a circular mask diameter or < 1.0 to shrink the mask. Default: 1.0. :param algorithm_ordersubsets: The number of ordered-subsets to accelerate reconstruction. Default: 6. :param algorithm_nonnegativity: ENABLE or DISABLE nonnegativity constraint. Default: 'ENABLE'. :param regularisation_method: To regularise choose methods ROF_TV, FGP_TV, PD_TV, SB_TV, LLT_ROF,\ NDF, TGV, NLTV, Diff4th. Default: 'FGP_TV'. :param regularisation_parameter: Regularisation (smoothing) value, higher \ the value stronger the smoothing effect. Default: 0.00001. :param regularisation_iterations: The number of regularisation iterations. Default: 80. :param regularisation_device: The number of regularisation iterations. Default: 'gpu'. :param regularisation_PD_lip: Primal-dual parameter for convergence. Default: 8. :param regularisation_methodTV: 0/1 - TV specific isotropic/anisotropic choice. Default: 0. :param regularisation_timestep: Time marching parameter, relevant for \ (ROF_TV, LLT_ROF, NDF, Diff4th) penalties. Default: 0.003. :param regularisation_edge_thresh: 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 regularisation_NDF_penalty: NDF specific penalty type Huber, Perona, Tukey. Default: 'Huber'. """ def __init__(self): super(TomobarRecon3d, self).__init__("TomobarRecon3d") def _get_output_size(self, in_data): sizeX = self.parameters['output_size'] shape = in_data.get_shape() if sizeX == 'auto': detX = in_data.get_data_dimension_by_axis_label('detector_x') sizeX = shape[detX] return sizeX def set_filter_padding(self, in_pData, out_pData): self.pad = self.parameters['padding'] in_data = self.get_in_datasets()[0] det_y = in_data.get_data_dimension_by_axis_label('detector_y') pad_det_y = '%s.%s' % (det_y, self.pad) pad_dict = {'pad_directions': [pad_det_y], 'pad_mode': 'edge'} in_pData[0].padding = pad_dict out_pData[0].padding = pad_dict def setup(self): in_dataset = self.get_in_datasets()[0] self.parameters['vol_shape'] = self.parameters['output_size'] procs = self.exp.meta_data.get("processes") procs = len([i for i in procs if 'GPU' in i]) dim = in_dataset.get_data_dimension_by_axis_label('detector_y') nSlices = int(np.ceil(in_dataset.get_shape()[dim] / float(procs))) self._set_max_frames(nSlices) super(TomobarRecon3d, self).setup() def pre_process(self): in_pData = self.get_plugin_in_datasets()[0] out_pData = self.get_plugin_out_datasets()[0] detY = in_pData.get_data_dimension_by_axis_label('detector_y') # ! padding vertical detector ! self.Vert_det = in_pData.get_shape()[detY] + 2 * self.pad in_pData = self.get_plugin_in_datasets() self.det_dimX_ind = in_pData[0].get_data_dimension_by_axis_label( 'detector_x') self.det_dimY_ind = in_pData[0].get_data_dimension_by_axis_label( 'detector_y') self.output_size = out_pData.get_shape()[self.det_dimX_ind] # extract given parameters into dictionaries suitable for ToMoBAR input self._data_ = { 'OS_number': self.parameters['algorithm_ordersubsets'], 'huber_threshold': self.parameters['data_Huber_thresh'], 'ringGH_lambda': self.parameters['data_full_ring_GH'], 'ringGH_accelerate': self.parameters['data_full_ring_accelerator_GH'] } self._algorithm_ = { 'iterations': self.parameters['algorithm_iterations'], 'nonnegativity': self.parameters['algorithm_nonnegativity'], 'mask_diameter': self.parameters['algorithm_mask'], 'verbose': self.parameters['algorithm_verbose'] } self._regularisation_ = { 'method': self.parameters['regularisation_method'], 'regul_param': self.parameters['regularisation_parameter'], 'iterations': self.parameters['regularisation_iterations'], 'device_regulariser': self.parameters['regularisation_device'], 'edge_threhsold': self.parameters['regularisation_edge_thresh'], 'time_marching_step': self.parameters['regularisation_timestep'], 'regul_param2': self.parameters['regularisation_parameter2'], 'PD_LipschitzConstant': self.parameters['regularisation_PD_lip'], 'NDF_penalty': self.parameters['regularisation_NDF_penalty'], 'methodTV': self.parameters['regularisation_methodTV'] } def process_frames(self, data): cor, angles, self.vol_shape, init = self.get_frame_params() self.anglesRAD = np.deg2rad(angles.astype(np.float32)) projdata3D = data[0].astype(np.float32) dim_tuple = np.shape(projdata3D) self.Horiz_det = dim_tuple[self.det_dimX_ind] half_det_width = 0.5 * self.Horiz_det cor_astra = half_det_width - cor[0] projdata3D[projdata3D > 10**15] = 0.0 projdata3D = np.swapaxes(projdata3D, 0, 1) #print(f"Shape of projdata3D is {np.shape(projdata3D)}") self._data_.update({'projection_norm_data': projdata3D}) # if one selects PWLS or SWLS models then raw data is also required (2 inputs) if ((self.parameters['data_fidelity'] == 'PWLS') or (self.parameters['data_fidelity'] == 'SWLS')): rawdata3D = data[1].astype(np.float32) rawdata3D[rawdata3D > 10**15] = 0.0 rawdata3D = np.swapaxes(rawdata3D, 0, 1) / np.max( np.float32(rawdata3D)) #print(f"Shape of rawdata3D is {np.shape(rawdata3D)}") self._data_.update({'projection_raw_data': rawdata3D}) self._data_.update({ 'beta_SWLS': self.parameters['data_beta_SWLS'] * np.ones(self.Horiz_det) }) # set parameters and initiate a TomoBar class object self.Rectools = RecToolsIR( DetectorsDimH=self. Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV=self. Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset=cor_astra.item() - 0.5, # The center of rotation (CoR) scalar or a vector AnglesVec=self.anglesRAD, # the vector of angles in radians ObjSize=self. output_size, # a scalar to define the reconstructed object dimensions datafidelity=self.parameters[ 'data_fidelity'], # data fidelity, choose LS, PWLS, SWLS device_projector='gpu') # Run FISTA reconstrucion algorithm here recon = self.Rectools.FISTA(self._data_, self._algorithm_, self._regularisation_) recon = np.swapaxes(recon, 0, 1) return recon def nInput_datasets(self): return max(len(self.parameters['in_datasets']), 1) def nOutput_datasets(self): return 1 def _set_max_frames(self, frames): self._max_frames = frames def get_max_frames(self): return self._max_frames def get_slice_axis(self): return 'detector_y' 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
plt.subplot(133) plt.imshow(FBPrec[:, :, sliceSel], vmin=0, vmax=max_val) plt.title('3D FBP Reconstruction, sagittal view') plt.show() #%% print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print("Reconstructing with FISTA method (ASTRA used for projection)") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") from tomobar.methodsIR import RecToolsIR # set parameters and initiate a class object Rectools = RecToolsIR( DetectorsDimH=Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset=None, # Center of Rotation (CoR) scalar (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 or PWLS device_projector='gpu') _data_ = {'projection_norm_data': projData3D_analyt_noise} # data dictionary lc = Rectools.powermethod( _data_) # calculate Lipschitz constant (run once to initialise) # Run FISTA reconstrucion algorithm without regularisation _algorithm_ = {'iterations': 200, 'lipschitz_const': lc} # Run FISTA reconstrucion algorithm without regularisation RecFISTA = Rectools.FISTA(_data_, _algorithm_, {})
class TomobarRecon(BaseRecon, GpuPlugin): """ A Plugin to reconstruct full-field tomographic projection data using state-of-the-art regularised iterative algorithms from \ the ToMoBAR package. ToMoBAR includes FISTA and ADMM iterative methods and depends on the ASTRA toolbox and the CCPi RGL toolkit: \ https://github.com/vais-ral/CCPi-Regularisation-Toolkit. :param output_size: Number of rows and columns in the \ reconstruction. Default: 'auto'. :param iterations: Number of outer iterations for FISTA (default) or ADMM methods. Default: 20. :param datafidelity: Data fidelity, Least Squares only at the moment. Default: 'LS'. :param nonnegativity: Nonnegativity constraint, choose Enable 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 or automatic calculation. Default: 'power'. :param regularisation: To regularise choose methods 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.0001. :param regularisation_iterations: The number of regularisation iterations. Default: 350. :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'. :param tolerance: Tolerance to stop outer iterations earlier. Default: 5e-10. :param ring_variable: Regularisation variable for ring removal. Default: 0.0. :param ring_accelerator: Acceleration constant for ring removal (use with care). Default: 50.0. """ def __init__(self): super(TomobarRecon, self).__init__("TomobarRecon") def _shift(self, sinogram, centre_of_rotation): centre_of_rotation_shift = (sinogram.shape[0]/2) - centre_of_rotation result = ndimage.interpolation.shift(sinogram, (centre_of_rotation_shift, 0)) return result def pre_process(self): # extract given parameters self.iterationsFISTA = self.parameters['iterations'] 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.ring_variable = self.parameters['ring_variable'] self.ring_accelerator = self.parameters['ring_accelerator'] self.time_marching_parameter = self.parameters['time_marching_parameter'] self.edge_param = self.parameters['edge_param'] self.NDF_penalty = self.parameters['NDF_penalty'] self.output_size = self.parameters['output_size'] self.tolerance = self.parameters['tolerance'] 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.anglesRAD = 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,\ lambdaR_L1 = self.ring_variable,\ alpha_ring = self.ring_accelerator,\ NDF_penalty = self.NDF_penalty,\ tolerance_regul = 0.0,\ 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 TomoBar class object self.Rectools = RecToolsIR(DetectorsDimH = self.DetectorsDimH, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV = None, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset = None, # Center of Rotation (CoR) scalar (for 3D case only) AnglesVec = self.anglesRAD, # array of angles in radians ObjSize = self.vol_shape[0] , # a scalar to define the reconstructed object dimensions datafidelity=self.datafidelity,# data fidelity, choose LS, PWLS nonnegativity=self.nonnegativity, # enable nonnegativity constraint (set to 'on') OS_number = self.ordersubsets, # the number of subsets, NONE/(or > 1) ~ classical / ordered subsets tolerance = self.tolerance , # 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
# calculate errors Qtools = QualityTools(phantom_tm, recNumerical) RMSE = Qtools.rmse() print("Root Mean Square Error is {}".format(RMSE)) #%% print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print ("Reconstructing with FISTA-OS method using tomobar") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") # initialise tomobar ITERATIVE reconstruction class ONCE from tomobar.methodsIR import RecToolsIR RectoolsIR = RecToolsIR(DetectorsDimH = Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV = Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset = 0.0, # Center of Rotation (CoR) scalar (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 = 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 #RecFISTA_reg = RectoolsIR.FISTA(projData3D_analyt_noisy, iterationsFISTA = 5, regularisation = 'ROF_TV', lipschitz_const = lc) sliceSel = int(0.5*N_size) max_val = 1
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 tomobar.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 CenterRotOffset=None, # Center of Rotation (CoR) scalar (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) device_projector='gpu') # prepare dictionaries with parameters: _data_ = { 'projection_norm_data': data_norm[:, det_y_crop], 'projection_raw_data': data_raw[:, det_y_crop], 'OS_number': 6 } # data dictionary lc = Rectools.powermethod( _data_) # calculate Lipschitz constant (run once to initialise)
plt.subplot(133) plt.imshow(FBPrec[:,:,sliceSel],vmin=0, vmax=max_val) plt.title('3D FBP Reconstruction, sagittal view') plt.show() #%% print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print ("Reconstructing with FISTA method (ASTRA used for projection)") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") from tomobar.methodsIR import RecToolsIR # set parameters and initiate a class object Rectools = RecToolsIR(DetectorsDimH = Horiz_det, # Horizontal detector dimension DetectorsDimV = Vert_det, # Vertical detector dimension (3D case) CenterRotOffset = None, # Center of Rotation scalar or a vector AnglesVec = angles_rad, # A vector of projection angles in radians ObjSize = N_size, # Reconstructed object dimensions (scalar) datafidelity='LS', # Data fidelity, choose from LS, KL, PWLS device_projector='gpu') _data_ = {'projection_norm_data' : projData3D_analyt_noise} # data dictionary lc = Rectools.powermethod(_data_) # calculate Lipschitz constant (run once to initialise) # Run FISTA reconstrucion algorithm without regularisation _algorithm_ = {'iterations' : 200, 'lipschitz_const' : lc} # Run FISTA reconstrucion algorithm without regularisation RecFISTA = Rectools.FISTA(_data_, _algorithm_, {}) # adding regularisation using the CCPi regularisation toolkit
tiff.close() """ #%% print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print("Reconstructing with ADMM method using tomobar software") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") # initialise tomobar ITERATIVE reconstruction class ONCE from tomobar.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)
plt.colorbar(ticks=[0, 0.5, 1], orientation='vertical') plt.title('Misaligned noisy FBP 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 tomobar ITERATIVE reconstruction class ONCE from tomobar.methodsIR import RecToolsIR RectoolsIR = RecToolsIR( DetectorsDimH=P, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= None, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset=None, # Center of Rotation (CoR) scalar (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) device_projector='gpu') #%% print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print("Reconstructing analytical sinogram using SIRT (tomobar)...") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") # prepare dictionaries with parameters: _data_ = {'projection_norm_data': sino_an} # data dictionary _algorithm_ = {'iterations': 250} SIRTrec_ideal = RectoolsIR.SIRT(_data_, _algorithm_) # ideal reconstruction _data_ = {'projection_norm_data': noisy_zing_stripe} # data dictionary SIRTrec_error = RectoolsIR.SIRT(_data_, _algorithm_) # error reconstruction
plt.show() plt.figure() plt.imshow(abs(FBPrec_ideal - FBPrec_error), vmin=0, vmax=2, cmap="gray") plt.colorbar(ticks=[0, 0.5, 2], orientation='vertical') plt.title('FBP reconsrtuction differences') #%% print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print("Reconstructing using FISTA method (tomobar)") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") from tomobar.methodsIR import RecToolsIR RectoolsIR = RecToolsIR( DetectorsDimH=P, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= None, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset=None, # Center of Rotation (CoR) scalar (for 3D case only) AnglesVec=angles_rad, # array of angles in radians ObjSize=P, # a scalar to define reconstructed object dimensions datafidelity='LS', #data fidelity, choose LS device_projector='gpu') # prepare dictionaries with parameters: _data_ = {'projection_norm_data': noisy_zing_stripe} # data dictionary lc = RectoolsIR.powermethod( _data_) # calculate Lipschitz constant (run once to initialise) _algorithm_ = {'iterations': 350, 'lipschitz_const': lc} # adding regularisation using the CCPi regularisation toolkit _regularisation_ = { 'method': 'PD_TV', 'regul_param': 0.001,
# calculate errors Qtools = QualityTools(phantom_tm, recNumerical_dynamic) RMSE = Qtools.rmse() print("Root Mean Square Error is {} for dynamic flat fields normalisation". format(RMSE)) #%% print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print("Reconstructing with FISTA-OS method using tomobar") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") # initialise tomobar ITERATIVE reconstruction class ONCE from tomobar.methodsIR import RecToolsIR Rectools = RecToolsIR( DetectorsDimH=Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset=0.0, # Center of Rotation (CoR) scalar (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) device_projector='gpu') #%% # prepare dictionaries with parameters: _data_ = { 'projection_norm_data': projData3D_norm, 'projection_raw_data': projData3D_noisy / np.max(projData3D_noisy), 'OS_number': 10 } # data dictionary lc = Rectools.powermethod( _data_) # calculate Lipschitz constant (run once to initialise) # algorithm parameters
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 tomobar ITERATIVE reconstruction class ONCE from tomobar.methodsIR import RecToolsIR RectoolsIR = RecToolsIR( DetectorsDimH=P, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= None, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset=None, # Center of Rotation (CoR) scalar (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 (tomobar)...") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") iterationsSIRT = 250 SIRTrec_ideal = RectoolsIR.SIRT(sino_an, iterationsSIRT) # ideal reconstruction SIRTrec_error = RectoolsIR.SIRT(noisy_zing_stripe, iterationsSIRT) # error reconstruction
plt.figure() plt.rcParams.update({'font.size': 20}) plt.imshow(FBPrec, vmin=0, vmax=1, cmap="gray") plt.colorbar(ticks=[0, 0.5, 1], orientation='vertical') plt.title('FBP reconstruction') #%% print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print ("Reconstructing with ADMM method (ASTRA used for projection)") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") from tomobar.methodsIR import RecToolsIR # set parameters and initiate a class object Rectools = RecToolsIR(DetectorsDimH = P, # Horizontal detector dimension DetectorsDimV = None, # Vertical detector dimension CenterRotOffset = None, # Center of Rotation scalar AnglesVec = angles_rad, # A vector of projection angles in radians ObjSize = N_size, # Reconstructed object dimensions (scalar) datafidelity='LS', # Data fidelity, choose from LS, KL, PWLS device_projector='gpu') # prepare dictionaries with parameters: _data_ = {'projection_norm_data' : noisy_sino} # data dictionary _algorithm_ = {'iterations' : 15, 'ADMM_rho_const' : 4000.0} # adding regularisation using the CCPi regularisation toolkit _regularisation_ = {'method' : 'FGP_TV', 'regul_param' : 0.06, 'iterations' : 100, 'device_regulariser': 'gpu'}
plt.subplot(133) plt.imshow(FBPrec[:,:,sliceSel],vmin=0, vmax=max_val) plt.title('3D FBP Reconstruction, sagittal view') plt.show() #%% print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print ("Reconstructing with ADMM method (ASTRA used for projection)") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") from tomobar.methodsIR import RecToolsIR # set parameters and initiate a class object Rectools = RecToolsIR(DetectorsDimH = Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV = Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset = None, # Center of Rotation (CoR) scalar (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), 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') # Run ADMM reconstrucion algorithm with regularisation RecADMM_reg = Rectools.ADMM(projData3D_analyt_noise, rho_const = 2000.0, \ iterationsADMM = 20, \ regularisation = 'FGP_TV', \ regularisation_parameter = 0.0035,\ regularisation_iterations = 200) sliceSel = int(0.5*N_size)
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') #%% print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print("Reconstructing using FISTA method (tomobar)") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") from tomobar.methodsIR import RecToolsIR RectoolsIR = RecToolsIR( DetectorsDimH=P, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= None, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset=None, # Center of Rotation (CoR) scalar (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), 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') lc = RectoolsIR.powermethod() # calculate Lipschitz constant # Run FISTA reconstrucion algorithm with regularisation RecFISTA_LS_reg = RectoolsIR.FISTA(noisy_zing_stripe, iterationsFISTA=350, regularisation='ROF_TV', regularisation_parameter=0.003, lipschitz_const=lc)
# calculate errors Qtools = QualityTools(phantom_tm, recNumerical) RMSE = Qtools.rmse() print("Root Mean Square Error is {}".format(RMSE)) #%% print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print("Reconstructing with FISTA-OS method using tomobar") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") # initialise tomobar ITERATIVE reconstruction class ONCE from tomobar.methodsIR import RecToolsIR Rectools = RecToolsIR( DetectorsDimH=Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV= Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset=0.0, # Center of Rotation (CoR) scalar (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) device_projector='gpu') _data_ = { 'projection_norm_data': projData3D_analyt_noisy, 'OS_number': 10 } # data dictionary lc = Rectools.powermethod( _data_) # calculate Lipschitz constant (run once to initialise) # Run FISTA reconstrucion algorithm without regularisation _algorithm_ = {'iterations': 20, 'lipschitz_const': lc}
FBPrec = RectoolsDIR.FBP(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 tomobar.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 CenterRotOffset=None, # Center of Rotation (CoR) scalar (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) nonnegativity='ENABLE', # enable nonnegativity constraint (set to 'ENABLE') 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( dataRaw[:, :, slice_to_recon] ) # calculate Lipschitz constant (run once to initilise) RecFISTA_os_pwls = Rectools.FISTA(data_norm[:,:,slice_to_recon], \ dataRaw[:,:,slice_to_recon], \ iterationsFISTA = 15, \
# calculate errors Qtools = QualityTools(phantom_tm, recNumerical) RMSE = Qtools.rmse() print("Root Mean Square Error is {}".format(RMSE)) #%% print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print ("Reconstructing with FISTA-OS method using tomobar") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") # initialise tomobar ITERATIVE reconstruction class ONCE from tomobar.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='ENABLE', # enable nonnegativity constraint (set to 'ENABLE') 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_norm, iterationsFISTA = 5, lipschitz_const = lc) # Run FISTA reconstrucion algorithm with 3D regularisation RecFISTA_reg = RectoolsIR.FISTA(projData3D_norm, iterationsFISTA = 8, regularisation = 'FGP_TV', regularisation_parameter = 0.0007, regularisation_iterations = 200,
plt.rcParams.update({'font.size': 20}) plt.imshow(FBPrec, vmin=0, vmax=1, cmap="gray") plt.colorbar(ticks=[0, 0.5, 1], orientation='vertical') plt.title('FBP reconstruction') #%% print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print("Reconstructing with ADMM method (ASTRA used for projection)") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") from tomobar.methodsIR import RecToolsIR # 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 CenterRotOffset=None, # Center of Rotation (CoR) scalar (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) device_projector='gpu') # prepare dictionaries with parameters: _data_ = {'projection_norm_data': noisy_sino} # data dictionary _algorithm_ = {'iterations': 15, 'ADMM_rho_const': 4000.0} # adding regularisation using the CCPi regularisation toolkit _regularisation_ = { 'method': 'FGP_TV', 'regul_param': 0.06, 'iterations': 100, 'device_regulariser': 'gpu'
plt.rcParams.update({'font.size': 20}) plt.imshow(FBPrec, vmin=0, vmax=1, cmap="gray") plt.colorbar(ticks=[0, 0.5, 1], orientation='vertical') plt.title('FBP reconstruction') #%% print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print ("Reconstructing with FISTA method (ASTRA used for projection)") print ("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") from tomobar.methodsIR import RecToolsIR # 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 CenterRotOffset = None, # Center of Rotation (CoR) scalar (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') lc = Rectools.powermethod() # calculate Lipschitz constant (run once to initilise) # Run FISTA reconstrucion algorithm without regularisation RecFISTA = Rectools.FISTA(noisy_sino, iterationsFISTA = 200, lipschitz_const = lc) # Run FISTA reconstrucion algorithm with regularisation RecFISTA_reg = Rectools.FISTA(noisy_sino, iterationsFISTA = 30, \ regularisation = 'ROF_TV', \ initialise = FBPrec,\ regularisation_parameter = 0.05,\
FBPrec_misalign = Rectools.FBP( sino_misalign) # reconstruction with misalignment plt.figure() plt.imshow(FBPrec_misalign, vmin=0, vmax=1, cmap="gray") plt.title('FBP reconstruction of misaligned data using known exact shifts') #%% print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") print("Reconstructing using FISTA method (tomobar)") print("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%") from tomobar.methodsIR import RecToolsIR RectoolsIR = RecToolsIR( DetectorsDimH=P, # Horizontal detector dimension DetectorsDimV=None, # Vertical detector dimension (3D case) CenterRotOffset=None, # Center of Rotation scalar AnglesVec=angles_rad, # A vector of projection angles in radians ObjSize=N_size, # Reconstructed object dimensions (scalar) datafidelity='PWLS', # Data fidelity, choose from LS, KL, PWLS, SWLS device_projector='gpu') # prepare dictionaries with parameters # data dictionary _data_ = { 'projection_norm_data': sino_artifacts, 'projection_raw_data': sino_artifacts_raw / np.max(sino_artifacts_raw), 'OS_number': 10 } lc = RectoolsIR.powermethod( _data_) # calculate Lipschitz constant (run once to initialise) _algorithm_ = {'iterations': 30, 'mask_diameter': 0.9, 'lipschitz_const': lc}
ObjSize=N_size, # Reconstructed object dimensions (scalar) device_projector='gpu') FBPrec = RectoolsDIR.FBP(data_norm) 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 tomobar.methodsIR import RecToolsIR # set parameters and initiate a class object Rectools = RecToolsIR( DetectorsDimH=detectorHoriz, # Horizontal detector dimension DetectorsDimV=None, # Vertical detector dimension (3D case) CenterRotOffset=92, # Center of Rotation scalar AnglesVec=angles_rad, # A vector of projection angles in radians ObjSize=N_size, # Reconstructed object dimensions (scalar) datafidelity='PWLS', # Data fidelity, choose from LS, KL, PWLS device_projector='gpu') # prepare dictionaries with parameters: _data_ = { 'projection_norm_data': data_norm, 'projection_raw_data': data_raw, 'OS_number': 6 } # data dictionary lc = Rectools.powermethod( _data_) # calculate Lipschitz constant (run once to initialise) _algorithm_ = {'iterations': 20, 'lipschitz_const': lc}
class TomobarRecon3d(BaseRecon, GpuPlugin): """ A Plugin to reconstruct full-field tomographic projection data using state-of-the-art regularised iterative algorithms from \ the ToMoBAR package. ToMoBAR includes FISTA and ADMM iterative methods and depends on the ASTRA toolbox and the CCPi RGL toolkit: \ https://github.com/vais-ral/CCPi-Regularisation-Toolkit. :param output_size: The dimension of the reconstructed volume (only X-Y dimension). Default: 'auto'. :param padding: The amount of pixels to pad each slab of the cropped projection data. Default: 17. :param data_fidelity: Data fidelity, Least Squares only at the moment. Default: 'LS'. :param data_Huber_thresh: Threshold parameter for __Huber__ data fidelity . Default: None. :param data_any_rings: a parameter to suppress various artifacts including rings and streaks. Default: None. :param data_any_rings_winsizes: half window sizes to collect background information [detector, angles, num of projections]. Default: (9,7,9). :param data_any_rings_power: a power parameter for Huber model. Default: 1.5. :param data_full_ring_GH: Regularisation variable for full constant ring removal (GH model). Default: None. :param data_full_ring_accelerator_GH: Acceleration constant for GH ring removal. Default: 10.0. :param algorithm_iterations: Number of outer iterations for FISTA (default) or ADMM methods. Default: 20. :param algorithm_verbose: print iterations number and other messages ('off' by default). Default: 'off'. :param algorithm_ordersubsets: The number of ordered-subsets to accelerate reconstruction. Default: 6. :param algorithm_nonnegativity: ENABLE or DISABLE nonnegativity constraint. Default: 'ENABLE'. :param regularisation_method: To regularise choose methods ROF_TV, FGP_TV, PD_TV, SB_TV, LLT_ROF,\ NDF, TGV, Diff4th. Default: 'FGP_TV'. :param regularisation_parameter: Regularisation (smoothing) value, higher \ the value stronger the smoothing effect. Default: 0.00001. :param regularisation_iterations: The number of regularisation iterations. Default: 80. :param regularisation_device: The number of regularisation iterations. Default: 'gpu'. :param regularisation_PD_lip: Primal-dual parameter for convergence. Default: 8. :param regularisation_methodTV: 0/1 - TV specific isotropic/anisotropic choice. Default: 0. :param regularisation_timestep: Time marching parameter, relevant for \ (ROF_TV, LLT_ROF, NDF, Diff4th) penalties. Default: 0.003. :param regularisation_edge_thresh: 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 regularisation_NDF_penalty: NDF specific penalty type Huber, Perona, Tukey. Default: 'Huber'. """ def __init__(self): super(TomobarRecon3d, self).__init__("TomobarRecon3d") def _get_output_size(self, in_data): sizeX = self.parameters['output_size'] shape = in_data.get_shape() if sizeX == 'auto': detX = in_data.get_data_dimension_by_axis_label('detector_x') sizeX = shape[detX] return sizeX def set_filter_padding(self, in_pData, out_pData): self.pad = self.parameters['padding'] in_data = self.get_in_datasets()[0] det_y = in_data.get_data_dimension_by_axis_label('detector_y') pad_det_y = '%s.%s' % (det_y, self.pad) pad_dict = {'pad_directions': [pad_det_y], 'pad_mode': 'edge'} in_pData[0].padding = pad_dict out_pData[0].padding = pad_dict def setup(self): in_dataset, out_dataset = self.get_datasets() # reduce the data as per data_subset parameter self.preview_flag = \ self.set_preview(in_dataset[0], self.parameters['preview']) axis_labels = in_dataset[0].data_info.get('axis_labels')[0] dim_volX, dim_volY, dim_volZ = \ self.map_volume_dimensions(in_dataset[0]) axis_labels = {in_dataset[0]: [str(dim_volX) + '.voxel_x.voxels', str(dim_volY) + '.voxel_y.voxels', str(dim_volZ) + '.voxel_z.voxels']} # specify reconstructed volume dimensions self.output_size = self._get_output_size(in_dataset[0]) shape = list(in_dataset[0].get_shape()) rot_dim = in_dataset[0].get_data_dimension_by_axis_label( 'rotation_angle') detX_dim = in_dataset[0].get_data_dimension_by_axis_label('detector_x') shape[rot_dim] = self.output_size shape[detX_dim] = self.output_size # if there are only 3 dimensions then add a fourth for slicing # if len(shape) == 2: # axis_labels = [0]*3 # axis_labels[dim_volX] = 'voxel_x.voxels' # axis_labels[dim_volY] = 'voxel_y.voxels' # axis_labels[dim_volZ] = 'voxel_z.voxels' # axis_labels[3] = 'scan.number' # shape.append(1) if self.parameters['vol_shape'] == 'fixed': shape[dim_volX] = shape[dim_volZ] else: shape[dim_volX] = self.parameters['vol_shape'] shape[dim_volZ] = self.parameters['vol_shape'] if 'resolution' in self.parameters.keys(): shape[dim_volX] /= self.parameters['resolution'] shape[dim_volZ] /= self.parameters['resolution'] out_dataset[0].create_dataset(axis_labels=axis_labels, shape=tuple(shape)) out_dataset[0].add_volume_patterns(dim_volX, dim_volY, dim_volZ) ndims = range(len(shape)) core_dims = (dim_volX, dim_volY, dim_volZ) slice_dims = tuple(set(ndims).difference(set(core_dims))) out_dataset[0].add_pattern( 'VOLUME_3D', core_dims=core_dims, slice_dims=slice_dims) # set information relating to the plugin data in_pData, out_pData = self.get_plugin_datasets() procs = self.exp.meta_data.get("processes") procs = len([i for i in procs if 'GPU' in i]) dim = in_dataset[0].get_data_dimension_by_axis_label('detector_y') nSlices = int(np.ceil(shape[dim]/float(procs))) in_pData[0].plugin_data_setup('SINOGRAM', nSlices, slice_axis='detector_y') # in_pData[1].plugin_data_setup('PROJECTION', nSlices) # (for PWLS) # set pattern_name and nframes to process for all datasets out_pData[0].plugin_data_setup('VOLUME_XZ', nSlices) def pre_process(self): in_pData = self.get_plugin_in_datasets()[0] detY = in_pData.get_data_dimension_by_axis_label('detector_y') self.Vert_det = in_pData.get_shape()[detY] + 2*self.pad # extract given parameters into dictionaries suitable for ToMoBAR input self._data_ = {'OS_number' : self.parameters['algorithm_ordersubsets'], 'huber_threshold' : self.parameters['data_Huber_thresh'], 'ring_weights_threshold' : self.parameters['data_any_rings'], 'ring_tuple_halfsizes' : self.parameters['data_any_rings_winsizes'], 'ring_huber_power' : self.parameters['data_any_rings_power'], 'ringGH_lambda' : self.parameters['data_full_ring_GH'], 'ringGH_accelerate' : self.parameters['data_full_ring_accelerator_GH']} self._algorithm_ = {'iterations' : self.parameters['algorithm_iterations'], 'nonnegativity' : self.parameters['algorithm_nonnegativity'], 'verbose' : self.parameters['algorithm_verbose']} self._regularisation_ = {'method' : self.parameters['regularisation_method'], 'regul_param' : self.parameters['regularisation_parameter'], 'iterations' : self.parameters['regularisation_iterations'], 'device_regulariser' : self.parameters['regularisation_device'], 'edge_threhsold' : self.parameters['regularisation_edge_thresh'], 'time_marching_step' : self.parameters['regularisation_timestep'], 'regul_param2' : self.parameters['regularisation_parameter2'], 'PD_LipschitzConstant' : self.parameters['regularisation_PD_lip'], 'NDF_penalty' : self.parameters['regularisation_NDF_penalty'], 'methodTV' : self.parameters['regularisation_methodTV']} in_pData = self.get_plugin_in_datasets() self.det_dimX_ind = in_pData[0].get_data_dimension_by_axis_label('detector_x') self.det_dimY_ind = in_pData[0].get_data_dimension_by_axis_label('detector_y') def process_frames(self, data): centre_of_rotations, angles, self.vol_shape, init = self.get_frame_params() self.anglesRAD = np.deg2rad(angles.astype(np.float32)) self.centre_of_rotations = centre_of_rotations projdata3D = data[0].astype(np.float32) dim_tuple = np.shape(projdata3D) self.Horiz_det = dim_tuple[self.det_dimX_ind] #print(np.shape(projdata3D)) projdata3D =np.swapaxes(projdata3D,0,1) # WIP for PWLS fidelity # rawdata3D = data[1].astype(np.float32) # rawdata3D =np.swapaxes(rawdata3D,0,1)/np.max(np.float32(rawdata3D)) self._data_.update({'projection_norm_data' : projdata3D}) # set parameters and initiate a TomoBar class object self.Rectools = RecToolsIR(DetectorsDimH = self.Horiz_det, # DetectorsDimH # detector dimension (horizontal) DetectorsDimV = self.Vert_det, # DetectorsDimV # detector dimension (vertical) for 3D case only CenterRotOffset = 0.0, # Center of Rotation (CoR) scalar (for 3D case only) AnglesVec = self.anglesRAD, # array of angles in radians ObjSize = self.output_size, # a scalar to define the reconstructed object dimensions datafidelity=self.parameters['data_fidelity'],# data fidelity, choose LS device_projector='gpu') # Run FISTA reconstrucion algorithm here recon = self.Rectools.FISTA(self._data_, self._algorithm_, self._regularisation_) recon = np.swapaxes(recon,0,1) return recon def nInput_datasets(self): return 1 def nOutput_datasets(self): return 1 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