@@ -54,9 +54,10 @@ def FBP(
5454 data : cp .ndarray ,
5555 angles : np .ndarray ,
5656 center : Optional [float ] = None ,
57- filter_freq_cutoff : Optional [ float ] = 0.35 ,
57+ filter_freq_cutoff : float = 0.35 ,
5858 recon_size : Optional [int ] = None ,
59- recon_mask_radius : Optional [float ] = 0.95 ,
59+ recon_mask_radius : float = 0.95 ,
60+ neglog : bool = False ,
6061 gpu_id : int = 0 ,
6162) -> cp .ndarray :
6263 """
@@ -81,6 +82,9 @@ def FBP(
8182 The radius of the circular mask that applies to the reconstructed slice in order to crop
8283 out some undesirable artifacts. The values outside the given diameter will be set to zero.
8384 It is recommended to keep the value in the range [0.7-1.0].
85+ neglog: bool
86+ Take negative logarithm on input data to convert to attenuation coefficient or a density of the scanned object. Defaults to False,
87+ assuming that the negative log is taken either in normalisation procedure on with Paganin filter application.
8488 gpu_id : int
8589 A GPU device index to perform operation on.
8690
@@ -94,7 +98,7 @@ def FBP(
9498 )
9599
96100 reconstruction = RecToolsCP .FBP (
97- data ,
101+ _take_neg_log ( data ) if neglog else data ,
98102 cutoff_freq = filter_freq_cutoff ,
99103 recon_mask_radius = recon_mask_radius ,
100104 data_axes_labels_order = input_data_axis_labels ,
@@ -110,6 +114,7 @@ def LPRec(
110114 center : Optional [float ] = None ,
111115 recon_size : Optional [int ] = None ,
112116 recon_mask_radius : Optional [float ] = 0.95 ,
117+ neglog : bool = False ,
113118) -> cp .ndarray :
114119 """
115120 Fourier direct inversion in 3D on unequally spaced (also called as Log-Polar) grids using
@@ -131,6 +136,9 @@ def LPRec(
131136 The radius of the circular mask that applies to the reconstructed slice in order to crop
132137 out some undesirable artifacts. The values outside the given diameter will be set to zero.
133138 It is recommended to keep the value in the range [0.7-1.0].
139+ neglog: bool
140+ Take negative logarithm on input data to convert to attenuation coefficient or a density of the scanned object. Defaults to False,
141+ assuming that the negative log is taken either in normalisation procedure on with Paganin filter application.
134142
135143 Returns
136144 -------
@@ -140,7 +148,7 @@ def LPRec(
140148 RecToolsCP = _instantiate_direct_recon_class (data , angles , center , recon_size , 0 )
141149
142150 reconstruction = RecToolsCP .FOURIER_INV (
143- data ,
151+ _take_neg_log ( data ) if neglog else data ,
144152 recon_mask_radius = recon_mask_radius ,
145153 data_axes_labels_order = input_data_axis_labels ,
146154 )
@@ -156,12 +164,14 @@ def SIRT(
156164 recon_size : Optional [int ] = None ,
157165 iterations : Optional [int ] = 300 ,
158166 nonnegativity : Optional [bool ] = True ,
167+ neglog : bool = False ,
159168 gpu_id : int = 0 ,
160169) -> cp .ndarray :
161170 """
162171 Perform Simultaneous Iterative Recostruction Technique (SIRT) using ASTRA toolbox :cite:`van2016fast` and
163172 ToMoBAR :cite:`kazantsev2020tomographic` wrappers.
164- This is 3D recon directly from a CuPy array while using ASTRA GPUlink capability.
173+ This is 3D recon directly from a CuPy array while using ASTRA GPUlink capability to avoid host-device
174+ transactions for projection and backprojection.
165175
166176 Parameters
167177 ----------
@@ -178,6 +188,9 @@ def SIRT(
178188 The number of SIRT iterations.
179189 nonnegativity : bool, optional
180190 Impose nonnegativity constraint on reconstructed image.
191+ neglog: bool
192+ Take negative logarithm on input data to convert to attenuation coefficient or a density of the scanned object. Defaults to False,
193+ assuming that the negative log is taken either in normalisation procedure on with Paganin filter application.
181194 gpu_id : int, optional
182195 A GPU device index to perform operation on.
183196
@@ -187,11 +200,16 @@ def SIRT(
187200 The SIRT reconstructed volume as a CuPy array.
188201 """
189202 RecToolsCP = _instantiate_iterative_recon_class (
190- data , angles , center , recon_size , gpu_id , datafidelity = "LS"
203+ data ,
204+ angles ,
205+ center ,
206+ recon_size ,
207+ gpu_id ,
208+ datafidelity = "LS" ,
191209 )
192210
193211 _data_ = {
194- "projection_norm_data" : data ,
212+ "projection_norm_data" : _take_neg_log ( data ) if neglog else data ,
195213 "data_axes_labels_order" : input_data_axis_labels ,
196214 } # data dictionary
197215 _algorithm_ = {
@@ -211,12 +229,14 @@ def CGLS(
211229 recon_size : Optional [int ] = None ,
212230 iterations : Optional [int ] = 20 ,
213231 nonnegativity : Optional [bool ] = True ,
232+ neglog : bool = False ,
214233 gpu_id : int = 0 ,
215234) -> cp .ndarray :
216235 """
217- Perform Congugate Gradient Least Squares (CGLS) using ASTRA toolbox :cite:`van2016fast` and
236+ Perform Conjugate Gradient Least Squares (CGLS) using ASTRA toolbox :cite:`van2016fast` and
218237 ToMoBAR :cite:`kazantsev2020tomographic` wrappers.
219- This is 3D recon directly from a CuPy array while using ASTRA GPUlink capability.
238+ This is 3D recon directly from a CuPy array while using ASTRA GPUlink capability to avoid host-device
239+ transactions for projection and backprojection.
220240
221241 Parameters
222242 ----------
@@ -233,6 +253,9 @@ def CGLS(
233253 The number of CGLS iterations.
234254 nonnegativity : bool, optional
235255 Impose nonnegativity constraint on reconstructed image.
256+ neglog: bool
257+ Take negative logarithm on input data to convert to attenuation coefficient or a density of the scanned object. Defaults to False,
258+ assuming that the negative log is taken either in normalisation procedure on with Paganin filter application.
236259 gpu_id : int, optional
237260 A GPU device index to perform operation on.
238261
@@ -246,15 +269,14 @@ def CGLS(
246269 )
247270
248271 _data_ = {
249- "projection_norm_data" : data ,
272+ "projection_norm_data" : _take_neg_log ( data ) if neglog else data ,
250273 "data_axes_labels_order" : input_data_axis_labels ,
251274 } # data dictionary
252275 _algorithm_ = {"iterations" : iterations , "nonnegativity" : nonnegativity }
253276 reconstruction = RecToolsCP .CGLS (_data_ , _algorithm_ )
254277 cp ._default_memory_pool .free_all_blocks ()
255278 return cp .require (cp .swapaxes (reconstruction , 0 , 1 ), requirements = "C" )
256279
257-
258280## %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% ##
259281def _instantiate_direct_recon_class (
260282 data : cp .ndarray ,
@@ -329,3 +351,11 @@ def _instantiate_iterative_recon_class(
329351 device_projector = gpu_id ,
330352 )
331353 return RecToolsCP
354+
355+ def _take_neg_log (data : cp .ndarray ) -> cp .ndarray :
356+ """Taking negative log"""
357+ data [data <= 0 ] = 1
358+ data = - cp .log (data )
359+ data [cp .isnan (data )] = 6.0
360+ data [cp .isinf (data )] = 0
361+ return data
0 commit comments