Exemple #1
0
def circ_mask(arr, axis, ratio=1, val=0., ncore=None):
    """
    Apply circular mask to a 3D array.

    Parameters
    ----------
    arr : ndarray
            Arbitrary 3D array.
    axis : int
        Axis along which mask will be performed.
    ratio : int, optional
        Ratio of the mask's diameter in pixels to
        the smallest edge size along given axis.
    val : int, optional
        Value for the masked region.

    Returns
    -------
    ndarray
        Masked array.
    """
    arr = dtype.as_float32(arr)
    val = np.float32(val)
    _arr = arr.swapaxes(0, axis)
    dx, dy, dz = _arr.shape
    mask = _get_mask(dy, dz, ratio)

    with mproc.set_numexpr_threads(ncore):
        ne.evaluate('where(mask, _arr, val)', out=_arr)

    return _arr.swapaxes(0, axis)
Exemple #2
0
def remove_nan(arr, val=0., ncore=None):
    """
    Replace NaN values in array with a given value.

    Parameters
    ----------
    arr : ndarray
        Input array.
    val : float, optional
        Values to be replaced with NaN values in array.
    ncore : int, optional
        Number of cores that will be assigned to jobs.

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

    with mproc.set_numexpr_threads(ncore):
        ne.evaluate('where(arr!=arr, val, arr)', out=arr)

    return arr
Exemple #3
0
def remove_nan(arr, val=0., ncore=None):
    """
    Replace NaN values in array with a given value.

    Parameters
    ----------
    arr : ndarray
        Input array.
    val : float, optional
        Values to be replaced with NaN values in array.
    ncore : int, optional
        Number of cores that will be assigned to jobs.

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

    with mproc.set_numexpr_threads(ncore):
        ne.evaluate('where(arr!=arr, val, arr)', out=arr)

    return arr
Exemple #4
0
def circ_mask(arr, axis, ratio=1, val=0., ncore=None):
    """
    Apply circular mask to a 3D array.

    Parameters
    ----------
    arr : ndarray
            Arbitrary 3D array.
    axis : int
        Axis along which mask will be performed.
    ratio : int, optional
        Ratio of the mask's diameter in pixels to
        the smallest edge size along given axis.
    val : int, optional
        Value for the masked region.

    Returns
    -------
    ndarray
        Masked array.
    """
    arr = dtype.as_float32(arr)
    val = np.float32(val)
    _arr = arr.swapaxes(0, axis)
    dx, dy, dz = _arr.shape
    mask = _get_mask(dy, dz, ratio)

    with mproc.set_numexpr_threads(ncore):
        ne.evaluate('where(mask, _arr, val)', out=_arr)

    return _arr.swapaxes(0, axis)
Exemple #5
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
Exemple #6
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
Exemple #7
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
Exemple #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
Exemple #9
0
def remove_outlier(arr, dif, size=3, axis=0, ncore=None, out=None):
    """
    Remove high intensity bright spots from a 3D array along specified
    dimension.

    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)

    if ncore is None:
        ncore = mproc.mp.cpu_count()

    e = cf.ThreadPoolExecutor(ncore)
    slc = [slice(None)]*len(arr.shape)
    for i in range(arr.shape[axis]):
        slc[axis] = i
        e.submit(filters.median_filter, arr[slc], size=(size, size),
                 output=tmp[slc])
    e.shutdown()

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

    return out
Exemple #10
0
def normalize(arr, flat, dark, cutoff=None, ncore=None, out=None):
    """
    Normalize raw projection data using the flat and dark field projections.

    Parameters
    ----------
    arr : ndarray
        3D stack of projections.
    flat : ndarray
        3D flat field data.
    dark : ndarray
        3D dark field data.
    cutoff : float, optional
        Permitted maximum vaue for the normalized data.
    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
        Normalized 3D tomographic data.
    """
    arr = dtype.as_float32(arr)
    l = np.float32(1e-6)
    flat = np.mean(flat, axis=0, dtype=np.float32)
    dark = np.mean(dark, axis=0, dtype=np.float32)

    with mproc.set_numexpr_threads(ncore):
        #denom = ne.evaluate('flat-dark')
        #ne.evaluate('where(denom<l,l,denom)', out=denom)
        #out = ne.evaluate('arr-dark', out=out)
        denom = flat - dark
        denom[denom < l] = l
        out = arr - dark
        out[out < l] = l
        out[:] /= denom
        #ne.evaluate('out/denom', out=out, truediv=True)
        if cutoff is not None:
            cutoff = np.float32(cutoff)
            out[out > cutoff] = cutoff
            #ne.evaluate('where(out>cutoff,cutoff,out)', out=out)
    return out
Exemple #11
0
def minus_log(arr, ncore=None, out=None):
    """
    Computation of the minus log of a given array.

    Parameters
    ----------
    arr : ndarray
        3D stack of projections.
    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
        Minus-log of the input data.
    """
    arr = dtype.as_float32(arr)

    with mproc.set_numexpr_threads(ncore):
        out = ne.evaluate('-log(arr)', out=out)
    return out
Exemple #12
0
def minus_log(arr, ncore=None, out=None):
    """
    Computation of the minus log of a given array.

    Parameters
    ----------
    arr : ndarray
        3D stack of projections.
    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
        Minus-log of the input data.
    """
    arr = dtype.as_float32(arr)

    with mproc.set_numexpr_threads(ncore):
        out = ne.evaluate('-log(arr)', out=out)
    return out
Exemple #13
0
def normalize(arr, flat, dark, cutoff=None, ncore=None, out=None):
    """
    Normalize raw projection data using the flat and dark field projections.

    Parameters
    ----------
    arr : ndarray
        3D stack of projections.
    flat : ndarray
        3D flat field data.
    dark : ndarray
        3D dark field data.
    cutoff : float, optional
        Permitted maximum vaue for the normalized data.
    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
        Normalized 3D tomographic data.
    """
    arr = dtype.as_float32(arr)
    l = np.float32(1e-6)
    flat = np.mean(flat, axis=0, dtype=np.float32)
    dark = np.mean(dark, axis=0, dtype=np.float32)

    with mproc.set_numexpr_threads(ncore):
        denom = ne.evaluate('flat-dark')
        ne.evaluate('where(denom<l,l,denom)', out=denom)
        out = ne.evaluate('arr-dark', out=out)
        ne.evaluate('out/denom', out=out, truediv=True)
        if cutoff is not None:
            cutoff = np.float32(cutoff)
            ne.evaluate('where(out>cutoff,cutoff,out)', out=out)
    return out
Exemple #14
0
def normalize_nf(tomo,
                 flats,
                 dark,
                 flat_loc,
                 cutoff=None,
                 ncore=None,
                 out=None):
    """
    Normalize raw 3D projection data with flats taken more than once during
    tomography. Normalization for each projection is done with the mean of the
    nearest set of flat fields (nearest flat fields).

    Parameters
    ----------
    tomo : ndarray
        3D tomographic data.
    flats : ndarray
        3D flat field data.
    dark : ndarray
        3D dark field data.
    flat_loc : list of int
        Indices of flat field data within tomography
    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
        Normalized 3D tomographic data.
    """

    tomo = dtype.as_float32(tomo)
    flats = dtype.as_float32(flats)
    dark = dtype.as_float32(dark)
    l = np.float32(1e-6)
    if cutoff is not None:
        cutoff = np.float32(cutoff)
    if out is None:
        out = np.empty_like(tomo)

    dark = np.median(dark, axis=0)
    denom = np.empty_like(dark)

    num_flats = len(flat_loc)
    total_flats = flats.shape[0]
    total_tomo = tomo.shape[0]

    num_per_flat = total_flats // num_flats
    tend = 0

    for m, loc in enumerate(flat_loc):
        fstart = m * num_per_flat
        fend = (m + 1) * num_per_flat
        flat = np.median(flats[fstart:fend], axis=0)

        # Normalization can be parallelized much more efficiently outside this
        # for loop accounting for the nested parallelism arising from
        # chunking the total normalization and each chunked normalization
        tstart = 0 if m == 0 else tend
        tend = total_tomo if m >= num_flats-1 \
            else int(np.round((flat_loc[m+1]-loc)/2)) + loc
        tomo_l = tomo[tstart:tend]
        out_l = out[tstart:tend]
        with mproc.set_numexpr_threads(ncore):
            ne.evaluate('flat-dark', out=denom)
            ne.evaluate('where(denom<l,l,denom)', out=denom)
            ne.evaluate('(tomo_l-dark)/denom', out=out_l, truediv=True)
            if cutoff is not None:
                ne.evaluate('where(out_l>cutoff,cutoff,out_l)', out=out_l)

    return out
Exemple #15
0
def pad(arr, axis, npad=None, mode='constant', ncore=None, **kwargs):
    """
    Pad an array along specified axis.

    Parameters
    ----------
    arr : ndarray
        Input array.
    npad : int, optional
        New dimension after padding.
    axis : int, optional
        Axis along which padding will be performed.
    mode : str or function
        One of the following string values or a user supplied function.

        'constant'
            Pads with a constant value.
        'edge'
            Pads with the edge values of array.
    constant_values : float, optional
        Used in 'constant'. Pad value
    ncore : int, optional
        Number of cores that will be assigned to jobs.

    Returns
    -------
    ndarray
        Padded 3D array.
    """

    allowedkwargs = {'constant': ['constant_values'],
                     'edge': [], }

    kwdefaults = {'constant_values': 0, }

    if isinstance(mode, str):
        if mode not in allowedkwargs:
            raise ValueError("'mode' keyword value '{}' not in allowed values {}".format(mode, list(allowedkwargs.keys())))
        for key in kwargs:
            if key not in allowedkwargs[mode]:
                raise ValueError('%s keyword not in allowed keywords %s' %
                                 (key, allowedkwargs[mode]))
        for kw in allowedkwargs[mode]:
            kwargs.setdefault(kw, kwdefaults[kw])
    else:
        raise ValueError('mode keyword value must be string, got %s: ' %
                         type(mode))

    if npad is None:
        npad = _get_npad(arr.shape[axis])

    newshape = list(arr.shape)
    newshape[axis] += 2*npad

    slc_in, slc_l, slc_r, slc_l_v, slc_r_v = _get_slices(arr.shape, axis, npad)

    out = np.empty(newshape, dtype=arr.dtype)
    if arr.dtype in [np.float32, np.float64, np.bool,
                     np.int32, np.int64, np.complex128]:
        # Datatype supported by numexpr
        with mproc.set_numexpr_threads(ncore):
            ne.evaluate("arr", out=out[slc_in])
            if mode == 'constant':
                np_cast = getattr(np, str(arr.dtype))
                cval = np_cast(kwargs['constant_values'])
                ne.evaluate("cval", out=out[slc_l])
                ne.evaluate("cval", out=out[slc_r])
            elif mode == 'edge':
                ne.evaluate("vec", local_dict={'vec': arr[slc_l_v]},
                            out=out[slc_l])
                ne.evaluate("vec", local_dict={'vec': arr[slc_r_v]},
                            out=out[slc_r])
    else:
        # Datatype not supported by numexpr, use numpy instead
        out[slc_in] = arr
        if mode == 'constant':
            out[slc_l] = kwargs['constant_values']
            out[slc_r] = kwargs['constant_values']
        elif mode == 'edge':
            out[slc_l] = arr[slc_l_v]
            out[slc_r] = arr[slc_r_v]
    return out
Exemple #16
0
def normalize_nf(tomo, flats, dark, flat_loc,
                 cutoff=None, ncore=None, out=None):
    """
    Normalize raw 3D projection data with flats taken more than once during
    tomography. Normalization for each projection is done with the mean of the
    nearest set of flat fields (nearest flat fields).

    Parameters
    ----------
    tomo : ndarray
        3D tomographic data.
    flats : ndarray
        3D flat field data.
    dark : ndarray
        3D dark field data.
    flat_loc : list of int
        Indices of flat field data within tomography
    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
        Normalized 3D tomographic data.
    """

    tomo = dtype.as_float32(tomo)
    flats = dtype.as_float32(flats)
    dark = dtype.as_float32(dark)
    l = np.float32(1e-6)
    if cutoff is not None:
        cutoff = np.float32(cutoff)
    if out is None:
        out = np.empty_like(tomo)

    dark = np.median(dark, axis=0)
    denom = np.empty_like(dark)

    num_flats = len(flat_loc)
    total_flats = flats.shape[0]
    total_tomo = tomo.shape[0]

    num_per_flat = total_flats//num_flats
    tend = 0

    for m, loc in enumerate(flat_loc):
        fstart = m*num_per_flat
        fend = (m + 1)*num_per_flat
        flat = np.median(flats[fstart:fend], axis=0)

        # Normalization can be parallelized much more efficiently outside this
        # for loop accounting for the nested parallelism arising from
        # chunking the total normalization and each chunked normalization
        tstart = 0 if m == 0 else tend
        tend = total_tomo if m >= num_flats-1 \
                          else int(np.round((flat_loc[m+1]-loc)/2)) + loc
        tomo_l = tomo[tstart:tend]
        out_l = out[tstart:tend]
        with mproc.set_numexpr_threads(ncore):
            ne.evaluate('flat-dark', out=denom)
            ne.evaluate('where(denom<l,l,denom)', out=denom)
            ne.evaluate('(tomo_l-dark)/denom', out=out_l, truediv=True)
            if cutoff is not None:
                ne.evaluate('where(out_l>cutoff,cutoff,out_l)', out=out_l)

    return out
Exemple #17
0
def pad(arr, axis, npad=None, mode='constant', ncore=None, **kwargs):
    """
    Pad an array along specified axis.

    Parameters
    ----------
    arr : ndarray
        Input array.
    npad : int, optional
        New dimension after padding.
    axis : int, optional
        Axis along which padding will be performed.
    mode : str or function
        One of the following string values or a user supplied function.

        'constant'
            Pads with a constant value.
        'edge'
            Pads with the edge values of array.
    constant_values : float, optional
        Used in 'constant'. Pad value
    ncore : int, optional
        Number of cores that will be assigned to jobs.

    Returns
    -------
    ndarray
        Padded 3D array.
    """

    allowedkwargs = {
        'constant': ['constant_values'],
        'edge': [],
    }

    kwdefaults = {
        'constant_values': 0,
    }

    if isinstance(mode, str):
        if mode not in allowedkwargs:
            raise ValueError(
                "'mode' keyword value '{}' not in allowed values {}".format(
                    mode, list(allowedkwargs.keys())))
        for key in kwargs:
            if key not in allowedkwargs[mode]:
                raise ValueError('%s keyword not in allowed keywords %s' %
                                 (key, allowedkwargs[mode]))
        for kw in allowedkwargs[mode]:
            kwargs.setdefault(kw, kwdefaults[kw])
    else:
        raise ValueError('mode keyword value must be string, got %s: ' %
                         type(mode))

    if npad is None:
        npad = _get_npad(arr.shape[axis])

    newshape = list(arr.shape)
    newshape[axis] += 2 * npad

    slc_in, slc_l, slc_r, slc_l_v, slc_r_v = _get_slices(arr.shape, axis, npad)
    # convert to tuples
    slc_in = tuple(slc_in)
    slc_l = tuple(slc_l)
    slc_r = tuple(slc_r)
    slc_l_v = tuple(slc_l_v)
    slc_r_v = tuple(slc_r_v)

    out = np.empty(newshape, dtype=arr.dtype)
    if arr.dtype in [
            np.float32, np.float64, np.bool, np.int32, np.int64, np.complex128
    ]:
        # Datatype supported by numexpr
        with mproc.set_numexpr_threads(ncore):
            ne.evaluate("arr", out=out[slc_in])
            if mode == 'constant':
                np_cast = getattr(np, str(arr.dtype))
                cval = np_cast(kwargs['constant_values'])
                ne.evaluate("cval", out=out[slc_l])
                ne.evaluate("cval", out=out[slc_r])
            elif mode == 'edge':
                ne.evaluate("vec",
                            local_dict={'vec': arr[slc_l_v]},
                            out=out[slc_l])
                ne.evaluate("vec",
                            local_dict={'vec': arr[slc_r_v]},
                            out=out[slc_r])
    else:
        # Datatype not supported by numexpr, use numpy instead
        out[slc_in] = arr
        if mode == 'constant':
            out[slc_l] = kwargs['constant_values']
            out[slc_r] = kwargs['constant_values']
        elif mode == 'edge':
            out[slc_l] = arr[slc_l_v]
            out[slc_r] = arr[slc_r_v]
    return out