Example #1
0
def _dist_recon(tomo, center, recon, algorithm, args, kwargs, ncore, nchunk):
    axis_size = recon.shape[0]
    ncore, slcs = mproc.get_ncore_slices(axis_size, ncore, nchunk)

    if len(slcs) < ncore:
        ncore = int(len(slcs))

    # calculate how many real slices there are
    use_slcs = []
    nreal = 0
    for slc in slcs:
        _tomo = tomo[slc]
        _min = min(_tomo.shape)
        if _min > 0:
            nreal += 1
            use_slcs.append(slc)

    # if less real slices than ncores, reduce number of cores
    if nreal < ncore:
        ncore = int(nreal)

    # check if ncore is limited by env variable
    pythreads = os.environ.get("TOMOPY_PYTHON_THREADS")
    if pythreads is not None and ncore > int(pythreads):
        print(
            "Warning! 'TOMOPY_PYTHON_THREADS' has been set to '{0}', which is less than"
            " specified ncore={1}. Limiting ncore to {0}...".format(
                pythreads, ncore))
        ncore = int(pythreads)

    print("Reconstructing {} slice groups with {} master threads...".format(
        len(slcs), ncore))

    # this is used internally to prevent oversubscription
    os.environ["TOMOPY_PYTHON_THREADS"] = "{}".format(ncore)

    if ncore == 1:
        for slc in use_slcs:
            # run in this thread (useful for debugging)
            algorithm(tomo[slc], center[slc], recon[slc], *args, **kwargs)
    else:
        # execute recon on ncore threads
        with cf.ThreadPoolExecutor(ncore) as e:
            for slc in use_slcs:
                e.submit(algorithm, tomo[slc], center[slc], recon[slc], *args,
                         **kwargs)

    if pythreads is not None:
        # reset to default
        os.environ["TOMOPY_PYTHON_THREADS"] = "{}".format(pythreads)
    elif os.environ.get("TOMOPY_PYTHON_THREADS"):
        # if no default set, then
        del os.environ["TOMOPY_PYTHON_THREADS"]

    return recon
Example #2
0
def remove_outlier1d(arr, dif, size=3, axis=0, ncore=None, out=None):
    """
	Remove high intensity bright spots from an array, using a one-dimensional
	median filter along the specified axis.
	
	Dula: also removes dark spots
	
	Parameters
	----------
	arr : ndarray
		Input array.
	dif : float
		Expected difference value between outlier value and
		the median value of the array.
	size : int
		Size of the median filter.
	axis : int, optional
		Axis along which median filtering is performed.
	ncore : int, optional
		Number of cores that will be assigned to jobs.
	out : ndarray, optional
		Output array for result.  If same as arr, process will be done in-place.
	Returns
	-------
	ndarray
	   Corrected array.
	"""
    arr = arr.astype(np.float32, copy=False)
    dif = np.float32(dif)

    tmp = np.empty_like(arr)

    other_axes = [i for i in range(arr.ndim) if i != axis]
    largest = np.argmax([arr.shape[i] for i in other_axes])
    lar_axis = other_axes[largest]
    ncore, chnk_slices = mproc.get_ncore_slices(arr.shape[lar_axis],
                                                ncore=ncore)
    filt_size = [1] * arr.ndim
    filt_size[axis] = size

    with cf.ThreadPoolExecutor(ncore) as e:
        slc = [slice(None)] * arr.ndim
        for i in range(ncore):
            slc[lar_axis] = chnk_slices[i]
            e.submit(snf.median_filter,
                     arr[slc],
                     size=filt_size,
                     output=tmp[slc],
                     mode='mirror')

    with mproc.set_numexpr_threads(ncore):
        out = ne.evaluate('where(abs(arr-tmp)>=dif,tmp,arr)', out=out)

    return out
Example #3
0
def remove_outlier(arr, dif, size=3, axis=0, ncore=None, out=None):
    """
    Remove high intensity bright spots from a N-dimensional array by chunking
    along the specified dimension, and performing (N-1)-dimensional median
    filtering along the other dimensions.

    Parameters
    ----------
    arr : ndarray
        Input array.
    dif : float
        Expected difference value between outlier value and
        the median value of the array.
    size : int
        Size of the median filter.
    axis : int, optional
        Axis along which to chunk.
    ncore : int, optional
        Number of cores that will be assigned to jobs.
    out : ndarray, optional
        Output array for result. If same as arr, process
        will be done in-place.

    Returns
    -------
    ndarray
       Corrected array.
    """
    tmp = np.empty_like(arr)

    ncore, chnk_slices = mproc.get_ncore_slices(arr.shape[axis], ncore=ncore)

    filt_size = [size] * arr.ndim
    filt_size[axis] = 1

    with cf.ThreadPoolExecutor(ncore) as e:
        slc = [slice(None)] * arr.ndim
        for i in range(ncore):
            slc[axis] = chnk_slices[i]
            e.submit(scipy.ndimage.median_filter,
                     arr[tuple(slc)],
                     size=filt_size,
                     output=tmp[tuple(slc)])

    arr = dtype.as_float32(arr)
    tmp = dtype.as_float32(tmp)
    dif = np.float32(dif)

    with mproc.set_numexpr_threads(ncore):
        out = ne.evaluate('where(arr-tmp>=dif,tmp,arr)', out=out)

    return out
Example #4
0
def _dist_recon(tomo, center, recon, algorithm, args, kwargs, ncore, nchunk):
    axis_size = recon.shape[0]
    ncore, slcs = mproc.get_ncore_slices(axis_size, ncore, nchunk)
    if ncore == 1:
        for slc in slcs:
            # run in this thread (useful for debugging)
            algorithm(tomo[slc], center[slc], recon[slc], *args, **kwargs)
    else:
        # execute recon on ncore threads
        with cf.ThreadPoolExecutor(ncore) as e:
            for slc in slcs:
                e.submit(algorithm, tomo[slc], center[slc], recon[slc], *args, **kwargs)
    return recon
Example #5
0
def _dist_recon(tomo, center, recon, algorithm, args, kwargs, ncore, nchunk):
    axis_size = recon.shape[0]
    ncore, slcs = mproc.get_ncore_slices(axis_size, ncore, nchunk)
    if ncore == 1:
        for slc in slcs:
            # run in this thread (useful for debugging)
            algorithm(tomo[slc], center[slc], recon[slc], *args, **kwargs)
    else:
        # execute recon on ncore threads
        with cf.ThreadPoolExecutor(ncore) as e:
            for slc in slcs:
                e.submit(algorithm, tomo[slc], center[slc], recon[slc], *args, **kwargs)
    return recon
Example #6
0
def remove_outlier1d(arr, dif, size=3, axis=0, ncore=None, out=None):
    """
    Remove high intensity bright spots from an array, using a one-dimensional
    median filter along the specified axis.

    Parameters
    ----------
    arr : ndarray
        Input array.
    dif : float
        Expected difference value between outlier value and
        the median value of the array.
    size : int
        Size of the median filter.
    axis : int, optional
        Axis along which median filtering is performed.
    ncore : int, optional
        Number of cores that will be assigned to jobs.
    out : ndarray, optional
        Output array for result. If same as arr, process
        will be done in-place.

    Returns
    -------
    ndarray
       Corrected array.
    """
    arr = dtype.as_float32(arr)
    dif = np.float32(dif)

    tmp = np.empty_like(arr)

    other_axes = [i for i in range(arr.ndim) if i != axis]
    largest = np.argmax([arr.shape[i] for i in other_axes])
    lar_axis = other_axes[largest]
    ncore, chnk_slices = mproc.get_ncore_slices(
        arr.shape[lar_axis], ncore=ncore)
    filt_size = [1]*arr.ndim
    filt_size[axis] = size

    with cf.ThreadPoolExecutor(ncore) as e:
        slc = [slice(None)]*arr.ndim
        for i in range(ncore):
            slc[lar_axis] = chnk_slices[i]
            e.submit(filters.median_filter, arr[slc], size=filt_size,
                     output=tmp[slc], mode='mirror')

    with mproc.set_numexpr_threads(ncore):
        out = ne.evaluate('where(arr-tmp>=dif,tmp,arr)', out=out)

    return out
Example #7
0
def _dist_recon(tomo, center, recon, algorithm, args, kwargs, ncore, nchunk):
    axis_size = recon.shape[0]
    ncore, slcs = mproc.get_ncore_slices(axis_size, ncore, nchunk)

    if len(slcs) < ncore:
        ncore = int(len(slcs))

    # calculate how many real slices there are
    use_slcs = []
    nreal = 0
    for slc in slcs:
        _tomo = tomo[slc]
        _min = min(_tomo.shape)
        if _min > 0:
            nreal += 1
            use_slcs.append(slc)

    # if less real slices than ncores, reduce number of cores
    if nreal < ncore:
        ncore = int(nreal)

    # check if ncore is limited by env variable
    pythreads = os.environ.get("TOMOPY_PYTHON_THREADS")
    if pythreads is not None and ncore > int(pythreads):
        print("Warning! 'TOMOPY_PYTHON_THREADS' has been set to '{0}', which is less than"
              " specified ncore={1}. Limiting ncore to {0}...".format(pythreads, ncore))
        ncore = int(pythreads)

    print("Reconstructing {} slice groups with {} master threads...".format(len(slcs), ncore))

    # this is used internally to prevent oversubscription
    os.environ["TOMOPY_PYTHON_THREADS"] = "{}".format(ncore)

    if ncore == 1:
        for slc in use_slcs:
            # run in this thread (useful for debugging)
            algorithm(tomo[slc], center[slc], recon[slc], *args, **kwargs)
    else:
        # execute recon on ncore threads
        with cf.ThreadPoolExecutor(ncore) as e:
            for slc in use_slcs:
                e.submit(algorithm, tomo[slc], center[slc], recon[slc], *args, **kwargs)

    if pythreads is not None:
        # reset to default
        os.environ["TOMOPY_PYTHON_THREADS"] = "{}".format(pythreads)
    elif os.environ.get("TOMOPY_PYTHON_THREADS"):
        # if no default set, then
        del os.environ["TOMOPY_PYTHON_THREADS"]

    return recon
Example #8
0
def remove_outlier(arr, dif, size=3, axis=0, ncore=None, out=None):
    """
    Remove high intensity bright spots from a N-dimensional array by chunking
    along the specified dimension, and performing (N-1)-dimensional median
    filtering along the other dimensions.

    Parameters
    ----------
    arr : ndarray
        Input array.
    dif : float
        Expected difference value between outlier value and
        the median value of the array.
    size : int
        Size of the median filter.
    axis : int, optional
        Axis along which to chunk.
    ncore : int, optional
        Number of cores that will be assigned to jobs.
    out : ndarray, optional
        Output array for result. If same as arr, process
        will be done in-place.

    Returns
    -------
    ndarray
       Corrected array.
    """
    arr = dtype.as_float32(arr)
    dif = np.float32(dif)

    tmp = np.empty_like(arr)

    ncore, chnk_slices = mproc.get_ncore_slices(arr.shape[axis], ncore=ncore)

    filt_size = [size]*arr.ndim
    filt_size[axis] = 1

    with cf.ThreadPoolExecutor(ncore) as e:
        slc = [slice(None)]*arr.ndim
        for i in range(ncore):
            slc[axis] = chnk_slices[i]
            e.submit(filters.median_filter, arr[tuple(slc)], size=filt_size,
                     output=tmp[tuple(slc)])

    with mproc.set_numexpr_threads(ncore):
        out = ne.evaluate('where(arr-tmp>=dif,tmp,arr)', out=out)

    return out
Example #9
0
def astra(tomo, center, recon, theta, **kwargs):
    """
    Reconstruct object using the ASTRA toolbox

    Extra options
    ----------
    method : str
        ASTRA reconstruction method to use.
    num_iter : int, optional
        Number of algorithm iterations performed.
    proj_type : str, optional
        ASTRA projector type to use (see ASTRA docs for more information):
            - 'cuda' (for GPU algorithms)
            - 'line', 'linear', or 'strip' (for CPU algorithms)
    gpu_list : list, optional
        List of GPU indices to use
    extra_options : dict, optional
        Extra options for the ASTRA config (i.e. those in cfg['option'])

    Example
    -------
    >>> import tomopy
    >>> obj = tomopy.shepp3d() # Generate an object.
    >>> ang = tomopy.angles(180) # Generate uniformly spaced tilt angles.
    >>> sim = tomopy.project(obj, ang) # Calculate projections.
    >>>
    >>> # Reconstruct object:
    >>> rec = tomopy.recon(sim, ang, algorithm=tomopy.astra,
    >>>       options={'method':'SART', 'num_iter':10*180,
    >>>       'proj_type':'linear',
    >>>       'extra_options':{'MinConstraint':0}})
    >>>
    >>> # Show 64th slice of the reconstructed object.
    >>> import pylab
    >>> pylab.imshow(rec[64], cmap='gray')
    >>> pylab.show()
    """
    # Lazy import ASTRA
    import astra as astra_mod

    # Unpack arguments
    nslices = tomo.shape[0]
    num_gridx = kwargs['num_gridx']
    num_gridy = kwargs['num_gridy']
    opts = kwargs['options']

    # Check options
    for o in needed_options['astra']:
        if o not in opts:
            logger.error("Option %s needed for ASTRA reconstruction." % (o, ))
            raise ValueError()
    for o in default_options['astra']:
        if o not in opts:
            opts[o] = default_options['astra'][o]

    niter = opts['num_iter']
    proj_type = opts['proj_type']

    # Create ASTRA geometries
    vol_geom = astra_mod.create_vol_geom((num_gridx, num_gridy))

    # Number of GPUs to use
    if proj_type == 'cuda':
        if opts['gpu_list'] is not None:
            import concurrent.futures as cf
            gpu_list = opts['gpu_list']
            ngpu = len(gpu_list)
            _, slcs = mproc.get_ncore_slices(nslices, ngpu)
            # execute recon on a thread per GPU
            with cf.ThreadPoolExecutor(ngpu) as e:
                for gpu, slc in zip(gpu_list, slcs):
                    e.submit(astra_rec_cuda, tomo[slc], center[slc],
                             recon[slc], theta, vol_geom, niter, proj_type,
                             gpu, opts)
        else:
            astra_rec_cuda(tomo, center, recon, theta, vol_geom, niter,
                           proj_type, None, opts)
    else:
        astra_rec_cpu(tomo, center, recon, theta, vol_geom, niter, proj_type,
                      opts)
Example #10
0
def astra(tomo, center, recon, theta, **kwargs):
    """
    Reconstruct object using the ASTRA toolbox

    Extra options
    ----------
    method : str
        ASTRA reconstruction method to use.
    num_iter : int, optional
        Number of algorithm iterations performed.
    proj_type : str, optional
        ASTRA projector type to use (see ASTRA docs for more information):
            - 'cuda' (for GPU algorithms)
            - 'line', 'linear', or 'strip' (for CPU algorithms)
    gpu_list : list, optional
        List of GPU indices to use
    extra_options : dict, optional
        Extra options for the ASTRA config (i.e. those in cfg['option'])

    Example
    -------
    >>> import tomopy
    >>> obj = tomopy.shepp3d() # Generate an object.
    >>> ang = tomopy.angles(180) # Generate uniformly spaced tilt angles.
    >>> sim = tomopy.project(obj, ang) # Calculate projections.
    >>>
    >>> # Reconstruct object:
    >>> rec = tomopy.recon(sim, ang, algorithm=tomopy.astra,
    >>>       options={'method':'SART', 'num_iter':10*180,
    >>>       'proj_type':'linear',
    >>>       'extra_options':{'MinConstraint':0}})
    >>>
    >>> # Show 64th slice of the reconstructed object.
    >>> import pylab
    >>> pylab.imshow(rec[64], cmap='gray')
    >>> pylab.show()
    """
    # Lazy import ASTRA
    import astra as astra_mod

    # Unpack arguments
    nslices = tomo.shape[0]
    num_gridx = kwargs['num_gridx']
    num_gridy = kwargs['num_gridy']
    opts = kwargs['options']

    # Check options
    for o in needed_options['astra']:
        if o not in opts:
            logger.error("Option %s needed for ASTRA reconstruction." % (o,))
            raise ValueError()
    for o in default_options['astra']:
        if o not in opts:
            opts[o] = default_options['astra'][o]

    niter = opts['num_iter']
    proj_type = opts['proj_type']

    # Create ASTRA geometries
    vol_geom = astra_mod.create_vol_geom((num_gridx, num_gridy))

    # Number of GPUs to use
    if proj_type == 'cuda':
        if opts['gpu_list'] is not None:
            import concurrent.futures as cf
            gpu_list = opts['gpu_list']
            ngpu = len(gpu_list)
            _, slcs = mproc.get_ncore_slices(nslices, ngpu)
            # execute recon on a thread per GPU
            with cf.ThreadPoolExecutor(ngpu) as e:
                for gpu, slc in zip(gpu_list, slcs):
                    e.submit(astra_rec_cuda, tomo[slc], center[slc], recon[slc],
                             theta, vol_geom, niter, proj_type, gpu, opts)
        else:
            astra_rec_cuda(tomo, center, recon, theta, vol_geom, niter,
                           proj_type, None, opts)
    else:
        astra_rec_cpu(tomo, center, recon, theta, vol_geom, niter,
                      proj_type, opts)
Example #11
0
def _dist_recon(tomo, center, recon, algorithm, args, kwargs, ncore, nchunk):
    axis_size = recon.shape[0]
    ncore, slcs = mproc.get_ncore_slices(axis_size, ncore, nchunk)

    if len(slcs) < ncore:
        ncore = int(len(slcs))

    # calculate how many real slices there are
    use_slcs = []
    nreal = 0
    for slc in slcs:
        _tomo = tomo[slc]
        _min = min(_tomo.shape)
        if _min > 0:
            nreal += 1
            use_slcs.append(slc)

    # if less real slices than ncores, reduce number of cores
    if nreal < ncore:
        ncore = int(nreal)

    # check if ncore is limited by env variable
    pythreads = os.environ.get("TOMOPY_PYTHON_THREADS")
    if pythreads is not None and ncore > int(pythreads):
        warnings.warn(
            "The environment variable 'TOMOPY_PYTHON_THREADS' is limiting "
            "the requested ncore={1} to {0} cores. "
            "Set ncore <= 'TOMOPY_PYTHON_THREADS'.".format(pythreads, ncore))
        ncore = int(pythreads)

    logger.info(
        "Reconstructing {} slice groups with {} master threads...".format(
            len(slcs), ncore))
    # this is used internally to prevent oversubscription
    os.environ["TOMOPY_PYTHON_THREADS"] = "{}".format(ncore)

    if ncore == 1:
        for slc in use_slcs:
            # run in this thread (useful for debugging)
            algorithm(tomo[slc], center[slc], recon[slc], *args, **kwargs)
    else:
        # execute recon on ncore processes. Accelerated methods have internal
        # thread-pool and NVIDIA NPP library does not support simulatenously
        # leveraging multiple devices within the same process
        if "accelerated" in kwargs and kwargs["accelerated"]:
            futures = []
            with cf.ProcessPoolExecutor(ncore) as e:
                for idx, slc in enumerate(use_slcs):
                    futures.append(
                        e.submit(_run_accel_algorithm, idx, algorithm,
                                 tomo[slc], center[slc], recon[slc], *args,
                                 **kwargs))

            for f, slc in zip(futures, use_slcs):
                if f.exception() is not None:
                    raise f.exception()
                recon[slc] = f.result()
        else:
            # execute recon on ncore threads
            with cf.ThreadPoolExecutor(ncore) as e:
                for slc in use_slcs:
                    e.submit(algorithm, tomo[slc], center[slc], recon[slc],
                             *args, **kwargs)

    if pythreads is not None:
        # reset to default
        os.environ["TOMOPY_PYTHON_THREADS"] = "{}".format(pythreads)
    elif os.environ.get("TOMOPY_PYTHON_THREADS"):
        # if no default set, then
        del os.environ["TOMOPY_PYTHON_THREADS"]

    return recon