def _optimize_center(data, theta, slice_no, center_init, tol): """ Find the distance between the rotation axis and the middle of the detector field-of-view. The function exploits systematic artifacts in reconstructed images due to shifts in the rotation center [1]. It uses image entropy as the error metric and ''Nelder-Mead'' routine (of the scipy optimization module) as the optimizer. Parameters ---------- data : ndarray Input data. slice_no : scalar The index of the slice to be used for finding optimal center. center_init : scalar The initial guess for the center. tol : scalar Desired sub-pixel accuracy. Returns ------- optimal_center : scalar This function returns the index of the center position that results in the minimum entropy in the reconstructed image. References ---------- [1] `SPIE Proceedings, Vol 6318, 631818(2006) \ <dx.doi.org/10.1117/12.679101>`_ """ # Make an initial reconstruction to adjust histogram limits. recon = Gridrec(data, airPixels=20, ringWidth=10) recon.reconstruct(data, theta=theta, center=center_init, slice_no=slice_no) # Adjust histogram boundaries according to reconstruction. hist_min = np.min(recon.data_recon) if hist_min < 0: hist_min = 2 * hist_min elif hist_min >= 0: hist_min = 0.5 * hist_min hist_max = np.max(recon.data_recon) if hist_max < 0: hist_max = 0.5 * hist_max elif hist_max >= 0: hist_max = 2 * hist_max # Magic is ready to happen... res = minimize(_costFunc, center_init, args=(data, recon, theta, slice_no, hist_min, hist_max), method='Nelder-Mead', tol=tol) # Have a look at what I found: print "calculated rotation center: " + str(np.squeeze(res.x)) return res.x
def diagnose_center(args): """ Diagnostic tools to find rotation center. Helps finding the rotation center manually by visual inspection of the selected reconstructions with different centers. The outputs for different centers are put into ``data/diagnose`` directory and the corresponding center positions are printed so that one can skim through the images and select the best. Parameters ---------- data : ndarray Input data. slice_no : scalar, optional The index of the slice to be used for diagnostics. center_start, center_end, center_step : scalar, optional Values of the start, end and step of the center values to be used for diagnostics. """ data, theta, dir_path, slice_no, center_start, center_end, center_step = args num_projections = data.shape[0] num_slices = data.shape[1] num_pixels = data.shape[2] # Define diagnose region. if slice_no is None: slice_no = num_slices / 2 if center_start is None: center_start = (num_pixels / 2) - 20 if center_end is None: center_end = (num_pixels / 2) + 20 if center_step is None: center_step = 1 center_step /= 2. # Make preperations for the slices and corresponding centers. slice_data = data[:, slice_no, :] center = np.arange(center_start, center_end, center_step) num_center = center.size stacked_slices = np.zeros((num_projections, num_center, num_pixels)) for m in range(num_center): stacked_slices[:, m, :] = slice_data # Reconstruct the same slice with different centers. recon = Gridrec(stacked_slices) recon.run(stacked_slices, center=center, theta=theta) # Save it to a temporary directory for manual inspection. for m in range(center.size): if m % 2 == 0: # 2 slices same bec of gridrec img = misc.toimage(recon.data_recon[m, :, :]) file_name = dir_path + str(np.squeeze(center[m])) + ".tif" img.save(file_name)
def gridrec_wrapper(TomoObj, *args, **kwargs): if not TomoObj.FLAG_DATA: logger.warning("optimize rotation center (data missing) [bypassed]") return if not TomoObj.FLAG_THETA: logger.warning("optimize rotation center (angles missing) [bypassed]") return # Find center if center is absent. if not hasattr(TomoObj, 'center'): TomoObj.center = optimize_center(TomoObj.data, TomoObj.theta) recon = Gridrec(TomoObj.data, *args, **kwargs) recon.run(TomoObj.data, center=TomoObj.center, theta=TomoObj.theta) TomoObj.data_recon = recon.data_recon TomoObj.gridrec_pars = recon.params TomoObj.FLAG_DATA_RECON = True TomoObj.provenance['gridrec'] = (args, kwargs) logger.info("gridrec reconstruction [ok]")
def diagnose_center( data, theta, dir_path, slice_no, center_start, center_end, center_step, mask, ratio, dtype, data_min, data_max ): """ Diagnostic tools to find rotation center. Helps finding the rotation center manually by visual inspection of the selected reconstructions with different centers. The outputs for different centers are put into ``data/diagnose`` directory and the corresponding center positions are printed so that one can skim through the images and select the best. Parameters ---------- data : ndarray, float32 3-D tomographic data with dimensions: [projections, slices, pixels] theta : ndarray, float32 Projection angles. dir_path : str Directory to save output images. slice_no : scalar The index of the slice to be used for diagnostics. center_start, center_end, center_step : scalar Values of the start, end and step of the center values to be used for diagnostics. mask : bool If ``True`` applies a circular mask to the image. ratio : scalar The ratio of the radius of the circular mask to the edge of the reconstructed image. dtype : bool, optional Export data type precision. data_min, data_max : scalar, optional User defined minimum and maximum values of the reconstructions that will be used to scale the images when saving. Examples -------- - Finding rotation center by visual inspection: >>> import tomopy >>> >>> # Load data >>> myfile = 'demo/data.h5' >>> data, white, dark, theta = tomopy.xtomo_reader(myfile) >>> >>> # Construct tomo object >>> d = tomopy.xtomo_dataset(log='error') >>> d.dataset(data, white, dark, theta) >>> d.normalize() >>> >>> # Perform reconstructions with different centers. >>> d.diagnose_center(center_start=640, center_end=670) >>> print "Images are succesfully saved at tmp/" """ num_projections = data.shape[0] num_pixels = data.shape[2] # Don't ask why. Just do that. center_step /= 2.0 # Make preperations for the slices and corresponding centers. slice_data = data[:, slice_no, :] center = np.arange(center_start, center_end, center_step, dtype=np.float32) num_center = center.size stacked_slices = np.zeros((num_projections, num_center, num_pixels), dtype=np.float32) for m in range(num_center): stacked_slices[:, m, :] = slice_data # Reconstruct the same slice with different centers. recon = Gridrec(stacked_slices) recon.reconstruct(stacked_slices, theta=theta, center=center) # Apply circular mask. if mask is True: rad = num_pixels / 2 y, x = np.ogrid[-rad:rad, -rad:rad] msk = x * x + y * y > ratio * ratio * rad * rad for m in range(center.size): recon.data_recon[m, msk] = 0 # Find max min of data for scaling if data_max is None: data_max = np.max(recon.data_recon) if data_min is None: data_min = np.min(recon.data_recon) if data_max < np.max(recon.data_recon): recon.data_recon[recon.data_recon > data_max] = data_max if data_min > np.min(recon.data_recon): recon.data_recon[recon.data_recon < data_min] = data_min # Save it to a temporary directory for manual inspection. for m in range(center.size): if m % 2 == 0: # 2 slices same bec of gridrec. file_name = dir_path + str(np.squeeze(center[m])) + ".tif" arr = recon.data_recon[m, :, :] print data_min, data_max print np.min(arr), np.max(arr) if dtype is "uint8": arr = ((arr * 1.0 - data_min) / (data_max - data_min) * 255).astype("uint8") elif dtype is "uint16": arr = ((arr * 1.0 - data_min) / (data_max - data_min) * 65535).astype("uint16") elif dtype is "float32": arr = ((arr * 1.0 - data_min) / (data_max - data_min)).astype("float32") print np.min(arr), np.max(arr) with warnings.catch_warnings(): warnings.simplefilter("ignore") skimage_io.imsave(file_name, arr, plugin="tifffile") return dtype, data_max, data_min
def diagnose_center(data, theta, dir_path, slice_no, center_start, center_end, center_step, mask, ratio): """ Diagnostic tools to find rotation center. Helps finding the rotation center manually by visual inspection of the selected reconstructions with different centers. The outputs for different centers are put into ``data/diagnose`` directory and the corresponding center positions are printed so that one can skim through the images and select the best. Parameters ---------- data : ndarray, float32 3-D tomographic data with dimensions: [projections, slices, pixels] theta : ndarray, float32 Projection angles. dir_path : str Directory to save output images. slice_no : scalar The index of the slice to be used for diagnostics. center_start, center_end, center_step : scalar Values of the start, end and step of the center values to be used for diagnostics. mask : bool If ``True`` applies a circular mask to the image. ratio : scalar The ratio of the radius of the circular mask to the edge of the reconstructed image. Examples -------- - Finding rotation center by visual inspection: >>> import tomopy >>> >>> # Load data >>> myfile = 'demo/data.h5' >>> data, white, dark, theta = tomopy.xtomo_reader(myfile) >>> >>> # Construct tomo object >>> d = tomopy.xtomo_dataset(log='error') >>> d.dataset(data, white, dark, theta) >>> d.normalize() >>> >>> # Perform reconstructions with different centers. >>> d.diagnose_center(center_start=640, center_end=670) >>> print "Images are succesfully saved at tmp/" """ num_projections = data.shape[0] num_pixels = data.shape[2] # Don't ask why. Just do that. center_step /= 2. # Make preperations for the slices and corresponding centers. slice_data = data[:, slice_no, :] center = np.arange(center_start, center_end, center_step, dtype=np.float32) num_center = center.size stacked_slices = np.zeros((num_projections, num_center, num_pixels), dtype=np.float32) for m in range(num_center): stacked_slices[:, m, :] = slice_data # Reconstruct the same slice with different centers. recon = Gridrec(stacked_slices) recon.reconstruct(stacked_slices, theta=theta, center=center) # Apply circular mask. if mask is True: rad = num_pixels/2 y, x = np.ogrid[-rad:rad, -rad:rad] msk = x*x + y*y > ratio*ratio*rad*rad for m in range(center.size): recon.data_recon[m, msk] = 0 # Save it to a temporary directory for manual inspection. for m in range(center.size): if m % 2 == 0: # 2 slices same bec of gridrec. img = misc.toimage(recon.data_recon[m, :, :]) file_name = dir_path + str(np.squeeze(center[m])) + ".tif" img.save(file_name)
def optimize_center(data, theta, slice_no, center_init, tol, mask, ratio): """ Find the distance between the rotation axis and the middle of the detector field-of-view. The function exploits systematic artifacts in reconstructed images due to shifts in the rotation center [1]. It uses image entropy as the error metric and ''Nelder-Mead'' routine (of the scipy optimization module) as the optimizer. Parameters ---------- data : ndarray, float32 3-D tomographic data with dimensions: [projections, slices, pixels] slice_no : scalar The index of the slice to be used for finding optimal center. center_init : scalar The initial guess for the center. tol : scalar Desired sub-pixel accuracy. mask : bool If ``True`` applies a circular mask to the image. ratio : scalar The ratio of the radius of the circular mask to the edge of the reconstructed image. Returns ------- output : scalar This function returns the index of the center position that results in the minimum entropy in the reconstructed image. References ---------- [1] `SPIE Proceedings, Vol 6318, 631818(2006) \ <dx.doi.org/10.1117/12.679101>`_ Examples -------- - Finding rotation center automatically: >>> import tomopy >>> >>> # Load data >>> myfile = 'demo/data.h5' >>> data, white, dark, theta = tomopy.xtomo_reader(myfile, slices_start=0, slices_end=1) >>> >>> # Construct tomo object >>> d = tomopy.xtomo_dataset(log='error') >>> d.dataset(data, white, dark, theta) >>> d.normalize() >>> >>> # Find rotation center. >>> d.optimize_center() >>> >>> # Perform reconstruction >>> d.gridrec() >>> >>> # Save reconstructed data >>> output_file='tmp/recon_' >>> tomopy.xtomo_writer(d.data_recon, output_file) >>> print "Images are succesfully saved at " + output_file + '...' """ # Make an initial reconstruction to adjust histogram limits. recon = Gridrec(data, airPixels=20, ringWidth=10) recon.reconstruct(data, theta=theta, center=center_init, slice_no=slice_no) # Apply circular mask. if mask is True: rad = data.shape[2]/2 y, x = np.ogrid[-rad:rad, -rad:rad] msk = x*x + y*y > ratio*ratio*rad*rad recon.data_recon[0, msk] = 0 # Adjust histogram boundaries according to reconstruction. hist_min = np.min(recon.data_recon) if hist_min < 0: hist_min = 2 * hist_min elif hist_min >= 0: hist_min = 0.5 * hist_min hist_max = np.max(recon.data_recon) if hist_max < 0: hist_max = 0.5 * hist_max elif hist_max >= 0: hist_max = 2 * hist_max # Magic is ready to happen... res = minimize(_costFunc, center_init, args=(data, recon, theta, slice_no, hist_min, hist_max, mask, ratio), method='Nelder-Mead', tol=tol) # Have a look at what I found: print "calculated rotation center: " + str(np.squeeze(res.x)) return res.x
def diagnose_center(data, theta, dir_path, slice_no, center_start, center_end, center_step, mask, ratio, dtype, data_min, data_max): """ Diagnostic tools to find rotation center. Helps finding the rotation center manually by visual inspection of the selected reconstructions with different centers. The outputs for different centers are put into ``data/diagnose`` directory and the corresponding center positions are printed so that one can skim through the images and select the best. Parameters ---------- data : ndarray, float32 3-D tomographic data with dimensions: [projections, slices, pixels] theta : ndarray, float32 Projection angles. dir_path : str Directory to save output images. slice_no : scalar The index of the slice to be used for diagnostics. center_start, center_end, center_step : scalar Values of the start, end and step of the center values to be used for diagnostics. mask : bool If ``True`` applies a circular mask to the image. ratio : scalar The ratio of the radius of the circular mask to the edge of the reconstructed image. dtype : bool, optional Export data type precision. data_min, data_max : scalar, optional User defined minimum and maximum values of the reconstructions that will be used to scale the images when saving. Examples -------- - Finding rotation center by visual inspection: >>> import tomopy >>> >>> # Load data >>> myfile = 'demo/data.h5' >>> data, white, dark, theta = tomopy.xtomo_reader(myfile) >>> >>> # Construct tomo object >>> d = tomopy.xtomo_dataset(log='error') >>> d.dataset(data, white, dark, theta) >>> d.normalize() >>> >>> # Perform reconstructions with different centers. >>> d.diagnose_center(center_start=640, center_end=670) >>> print "Images are succesfully saved at tmp/" """ num_projections = data.shape[0] num_pixels = data.shape[2] # Don't ask why. Just do that. center_step /= 2. # Make preperations for the slices and corresponding centers. slice_data = data[:, slice_no, :] center = np.arange(center_start, center_end, center_step, dtype=np.float32) num_center = center.size stacked_slices = np.zeros((num_projections, num_center, num_pixels), dtype=np.float32) for m in range(num_center): stacked_slices[:, m, :] = slice_data # Reconstruct the same slice with different centers. recon = Gridrec(stacked_slices) recon.reconstruct(stacked_slices, theta=theta, center=center) # Apply circular mask. if mask is True: rad = num_pixels/2 y, x = np.ogrid[-rad:rad, -rad:rad] msk = x*x + y*y > ratio*ratio*rad*rad for m in range(center.size): recon.data_recon[m, msk] = 0 # Find max min of data for scaling if data_max is None: data_max = np.max(recon.data_recon) if data_min is None: data_min = np.min(recon.data_recon) if data_max < np.max(recon.data_recon): recon.data_recon[recon.data_recon>data_max] = data_max if data_min > np.min(recon.data_recon): recon.data_recon[recon.data_recon<data_min] = data_min # Save it to a temporary directory for manual inspection. for m in range(center.size): if m % 2 == 0: # 2 slices same bec of gridrec. file_name = dir_path + str(np.squeeze(center[m])) + ".tif" arr = recon.data_recon[m, :, :] if dtype is 'uint8': arr = ((arr*1.0 - data_min)/(data_max-data_min)*255).astype('uint8') elif dtype is 'uint16': arr = ((arr*1.0 - data_min)/(data_max-data_min)*65535).astype('uint16') elif dtype is 'float32': arr = ((arr*1.0 - data_min)/(data_max-data_min)).astype('float32') with warnings.catch_warnings(): warnings.simplefilter("ignore") skimage_io.imsave(file_name, arr, plugin='tifffile') return dtype, data_max, data_min