3333 from cupyx .scipy .ndimage import shift , gaussian_filter
3434 from skimage .registration import phase_cross_correlation
3535 from cupyx .scipy .fftpack import get_fft_plan
36- from cupyx .scipy .fft import rfft2 , fft2 , fftshift
36+ from cupyx .scipy .fft import fft2 , fftshift
3737else :
3838 load_cuda_module = Mock ()
3939 shift = Mock ()
5858def find_center_vo (
5959 data : cp .ndarray ,
6060 ind : Optional [int ] = None ,
61- average_radius : Optional [ int ] = 0 ,
61+ average_radius : int = 0 ,
6262 cor_initialisation_value : Optional [float ] = None ,
6363 smin : int = - 100 ,
6464 smax : int = 100 ,
@@ -77,24 +77,24 @@ def find_center_vo(
7777 3D [angles, detY, detX] tomographic data or a 2D [angles, detX] sinogram as a CuPy array.
7878 ind : int, optional
7979 Index of the slice to be used to estimate the CoR. If None is given, then the central sinogram will be extracted from the data array with a possible averaging, see .
80- average_radius : int, optional
80+ average_radius : int
8181 Averaging multiple sinograms around the ind-indexed sinogram to improve the signal-to-noise ratio. It is recommended to keep this parameter smaller than 10.
8282 cor_initialisation_value : float, optional
8383 The initial approximation for the centre of rotation. If the value is None, use the horizontal centre of the projection/sinogram image.
84- smin : int, optional
84+ smin : int
8585 Coarse search radius. Reference to the horizontal center of
8686 the sinogram.
87- smax : int, optional
87+ smax : int
8888 Coarse search radius. Reference to the horizontal center of
8989 the sinogram.
90- srad : float, optional
90+ srad : float
9191 Fine search radius.
92- step : float, optional
92+ step : float
9393 Step of fine searching.
94- ratio : float, optional
94+ ratio : float
9595 The ratio between the FOV of the camera and the size of object.
9696 It's used to generate the mask.
97- drop : int, optional
97+ drop : int
9898 Drop lines around vertical center of the mask.
9999
100100 Returns
@@ -148,11 +148,8 @@ def find_center_vo(
148148 if dsp_angle > 1 or dsp_detX > 1 :
149149 _sino_cs = _downsample (_sino_cs , dsp_angle , dsp_detX )
150150
151- # NOTE: this is correct implementation that avoids running any CUDA kernels. The performance is suboptimal
152151 init_cen = _search_coarse (_sino_cs , start_cor , stop_cor , ratio , drop )
153152
154- # NOTE: similar to the coarse module above, this is currently a correct function
155- # but it is NOT using CUDA kernels written. Therefore some kernels re-writing is needed.
156153 fine_cen = _search_fine (
157154 _sino_fs , fine_srange , step , float (init_cen ) * dsp_detX + off_set , ratio , drop
158155 )
@@ -218,53 +215,6 @@ def _search_fine(sino, srad, step, init_cen, ratio, drop):
218215 return cor
219216
220217
221- def _create_mask_numpy (nrow , ncol , radius , drop ):
222- du = 1.0 / ncol
223- dv = (nrow - 1.0 ) / (nrow * 2.0 * np .pi )
224- cen_row = np .int16 (np .ceil (nrow / 2.0 ) - 1 )
225- cen_col = np .int16 (np .ceil (ncol / 2.0 ) - 1 )
226- drop = min (drop , np .int16 (np .ceil (0.05 * nrow )))
227- mask = np .zeros ((nrow , ncol ), dtype = "float32" )
228- for i in range (nrow ):
229- pos = np .int16 (np .round (((i - cen_row ) * dv / radius ) / du ))
230- (pos1 , pos2 ) = np .clip (np .sort ((- pos + cen_col , pos + cen_col )), 0 , ncol - 1 )
231- mask [i , pos1 : pos2 + 1 ] = 1.0
232- mask [cen_row - drop : cen_row + drop + 1 , :] = 0.0
233- mask [:, cen_col - 1 : cen_col + 2 ] = 0.0
234- return mask
235-
236-
237- def _create_mask_half (nrow , ncol , radius , drop ):
238- du = 1.0 / ncol
239- dv = (nrow - 1.0 ) / (nrow * 2.0 * np .pi )
240- cen_row = int (math .ceil (nrow / 2.0 ) - 1 )
241- cen_col = int (math .ceil (ncol / 2.0 ) - 1 )
242- drop = min ([drop , int (math .ceil (0.05 * nrow ))])
243-
244- block_x = 128
245- block_y = 1
246- block_dims = (block_x , block_y )
247- grid_x = (ncol // 2 + 1 + block_x - 1 ) // block_x
248- grid_y = nrow
249- grid_dims = (grid_x , grid_y )
250- mask = cp .empty ((nrow , ncol // 2 + 1 ), dtype = "uint16" )
251- params = (
252- ncol ,
253- nrow ,
254- cen_col ,
255- cen_row ,
256- cp .float32 (du ),
257- cp .float32 (dv ),
258- cp .float32 (radius ),
259- cp .float32 (drop ),
260- mask ,
261- )
262- module = load_cuda_module ("generate_mask" )
263- kernel = module .get_function ("generate_mask" )
264- kernel (grid_dims , block_dims , params )
265- return mask
266-
267-
268218def _create_mask (nrow , ncol , radius , drop ):
269219 du = 1.0 / ncol
270220 dv = (nrow - 1.0 ) / (nrow * 2.0 * np .pi )
@@ -321,12 +271,10 @@ def _calculate_chunks(
321271
322272 available_memory -= shift_size
323273 freq_domain_size = (
324- # shift_size # it needs only half (RFFT), but complex64, so it's the same
325- shift_size
326- * 2 # it needs full (FFT), with complex64, so it's double
274+ shift_size * 2 # it needs full (FFT), with complex64, so it's double
327275 )
328276 fft_plan_size = freq_domain_size
329- size_per_shift = 2 * (fft_plan_size + freq_domain_size + shift_size )
277+ size_per_shift = 2.5 * (fft_plan_size + freq_domain_size + shift_size )
330278 nshift_max = available_memory // size_per_shift
331279 assert nshift_max > 0 , "Not enough memory to process"
332280 num_chunks = int (np .ceil (nshifts / nshift_max ))
@@ -357,10 +305,8 @@ def _calculate_metric(list_shift, sino, flip_sino, comp_sino, mask, out):
357305 # The sum is enough.
358306 masked_sum_abs_kernel = cp .ReductionKernel (
359307 in_params = "complex64 x, float32 mask" , # input, complex + mask
360- # in_params="complex64 x, uint16 mask", # input, complex + mask
361308 out_params = "float32 out" , # output, real
362309 map_expr = "abs(x) * mask" ,
363- # map_expr="mask ? abs(x) : 0.0f",
364310 reduce_expr = "a + b" ,
365311 post_map_expr = "out = a" ,
366312 identity = "0.0f" ,
@@ -421,7 +367,6 @@ def _calculate_metric(list_shift, sino, flip_sino, comp_sino, mask, out):
421367 # stack and transform
422368 # (we do the full sized mat FFT, even though the last chunk may be smaller, to
423369 # make sure we can re-use the same FFT plan as before)
424- # mat_freq = fft2(mat, axes=(1, 2), norm=None, plan=plan)
425370 mat_freq = fftshift (fft2 (mat , axes = (1 , 2 ), norm = None , plan = plan ), axes = (1 , 2 ))
426371
427372 masked_sum_abs_kernel (
@@ -789,7 +734,7 @@ def find_center_pc(
789734 proj2 : cp .ndarray ,
790735 tol : float = 0.5 ,
791736 rotc_guess : Union [float , Optional [str ]] = None ,
792- ) -> float :
737+ ) -> np . float32 :
793738 """
794739 Find rotation axis location by finding the offset between the first
795740 projection and a mirrored projection 180 degrees apart using
@@ -811,7 +756,7 @@ def find_center_pc(
811756
812757 Returns
813758 ----------
814- float
759+ np.float32
815760 Rotation axis location.
816761 """
817762 imgshift = 0.0 if rotc_guess is None else rotc_guess - (proj1 .shape [1 ] - 1.0 ) / 2.0
@@ -831,7 +776,7 @@ def find_center_pc(
831776 # registered translation with the second image
832777 center = (proj1 .shape [1 ] + shiftr [0 ][1 ] - 1.0 ) / 2.0
833778
834- return center + imgshift
779+ return np . float32 ( center + imgshift )
835780
836781
837782##%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
0 commit comments