Example #1
0
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
Example #2
0
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)
Example #3
0
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]")
Example #4
0
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
Example #5
0
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)
Example #6
0
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
Example #7
0
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