Exemple #1
0
    def __FilterDataFast(self):
        data = self.data[:,:,0]
        mode = _ni_support._extend_mode_to_code("reflect")
        # lowpass filter to suppress noise
        output, a = _ni_support._get_output(None, data)
        _nd_image.correlate1d(data, ofdP.weightsLowpass, 0, output, mode, 0, 0)
        _nd_image.correlate1d(output, ofdP.weightsLowpass, 1, output, mode, 0, 0)

        # lowpass filter again to find background
        output, b = _ni_support._get_output(None, data)
        _nd_image.correlate1d(data, ofdP.weightsHighpass, 0, output, mode, 0, 0)
        _nd_image.correlate1d(output, ofdP.weightsHighpass, 1, output, mode, 0, 0)

        return a - b
Exemple #2
0
def correlate1d(input, weights, axis=-1, output=None, mode="reflect",
                cval=0.0, origin=0):
    """Calculate a one-dimensional correlation along the given axis.

    The lines of the array along the given axis are correlated with the
    given weights.

    Parameters
    ----------
    %(input)s
    weights : array
        One-dimensional sequence of numbers.
    %(axis)s
    %(output)s
    %(mode)s
    %(cval)s
    %(origin)s
    """
    input = numpy.asarray(input)
    if numpy.iscomplexobj(input):
        raise TypeError('Complex type not supported')
    output, return_value = _ni_support._get_output(output, input)
    weights = numpy.asarray(weights, dtype=numpy.float64)
    if weights.ndim != 1 or weights.shape[0] < 1:
        raise RuntimeError('no filter weights given')
    if not weights.flags.contiguous:
        weights = weights.copy()
    axis = _ni_support._check_axis(axis, input.ndim)
    if ((len(weights) // 2 + origin < 0) or
        (len(weights) // 2 + origin > len(weights))):
        raise ValueError('invalid origin')
    mode = _ni_support._extend_mode_to_code(mode)
    _nd_image.correlate1d(input, weights, axis, output, mode, cval,
                          origin)
    return return_value
Exemple #3
0
    def __FilterData2D(self, data):
        mode = _ni_support._extend_mode_to_code("reflect")
        #lowpass filter to suppress noise
        #a = ndimage.gaussian_filter(data.astype('f4'), self.filterRadiusLowpass)
        #print data.shape

        data = data - data.mean()

        output, a = _ni_support._get_output(None, data)
        if self.PRIaxis == 'x':
            _nd_image.correlate1d(data, weightsLowpass, 0, output, mode, 0, 0)
            _nd_image.correlate1d(output, weightsHighpass, 1, output, mode, 0,
                                  0)
        else:
            _nd_image.correlate1d(data, weightsHighpass, 0, output, mode, 0, 0)
            _nd_image.correlate1d(output, weightsLowpass, 1, output, mode, 0,
                                  0)
        #print numpy.absolute(a - a_).mean()

        #lowpass filter again to find background
        #b = ndimage.gaussian_filter(a, self.filterRadiusHighpass)

        #output, b = _ni_support._get_output(None, data)
        #_nd_image.correlate1d(data, weightsHighpass, 0, output, mode, 0,0)
        #_nd_image.correlate1d(output, weightsHighpass, 1, output, mode, 0,0)

        return a  #- b
Exemple #4
0
    def __FilterData2D(self,data):
        mode = _ni_support._extend_mode_to_code("reflect")
        #lowpass filter to suppress noise
        #a = ndimage.gaussian_filter(data.astype('f4'), self.filterRadiusLowpass)
        #print data.shape
        
        data = data - data.mean()

        output, a = _ni_support._get_output(None, data)
        if self.PRIaxis == 'x':
            _nd_image.correlate1d(data, weightsLowpass, 0, output, mode, 0,0)
            _nd_image.correlate1d(output, weightsHighpass, 1, output, mode, 0,0)
        else:
            _nd_image.correlate1d(data, weightsHighpass, 0, output, mode, 0,0)
            _nd_image.correlate1d(output, weightsLowpass, 1, output, mode, 0,0)
        #print numpy.absolute(a - a_).mean()

        #lowpass filter again to find background
        #b = ndimage.gaussian_filter(a, self.filterRadiusHighpass)

        #output, b = _ni_support._get_output(None, data)
        #_nd_image.correlate1d(data, weightsHighpass, 0, output, mode, 0,0)
        #_nd_image.correlate1d(output, weightsHighpass, 1, output, mode, 0,0)

        return a #- b
Exemple #5
0
def square_gaussian_filter(input,
                           sigma,
                           output=None,
                           mode="reflect",
                           cval=0.0):
    """Multi-dimensional Squared Gaussian filter.

    The standard-deviations of the Gaussian filter are given for each
    axis as a sequence, or as a single number, in which case it is
    equal for all axes.

    Note: The multi-dimensional filter is implemented as a sequence of
    one-dimensional convolution filters. The intermediate arrays are
    stored in the same data type as the output. Therefore, for output
    types with a limited precision, the results may be imprecise
    because intermediate results may be stored with insufficient
    precision.
    """
    input = np.asarray(input)
    output, return_value = _ni_support._get_output(output, input)
    sigmas = _ni_support._normalize_sequence(sigma, input.ndim)
    axes = range(input.ndim)
    axes = [(axes[ii], sigmas[ii]) for ii in range(len(axes))
            if sigmas[ii] > 1e-15]
    if len(axes) > 0:
        for axis, sigma in axes:
            square_gaussian_filter1d(input, sigma, axis, output, mode, cval)
            input = output
    else:
        output[...] = input[...]
    return return_value
def square_gaussian_filter(input, sigma, output = None, mode = "reflect", cval = 0.0):
    """Multi-dimensional Squared Gaussian filter.

    The standard-deviations of the Gaussian filter are given for each
    axis as a sequence, or as a single number, in which case it is
    equal for all axes.

    Note: The multi-dimensional filter is implemented as a sequence of
    one-dimensional convolution filters. The intermediate arrays are
    stored in the same data type as the output. Therefore, for output
    types with a limited precision, the results may be imprecise
    because intermediate results may be stored with insufficient
    precision.
    """
    input = np.asarray(input)
    output, return_value =_ni_support._get_output(output, input)
    sigmas =_ni_support._normalize_sequence(sigma, input.ndim)
    axes = range(input.ndim)
    axes = [(axes[ii], sigmas[ii])
                        for ii in range(len(axes)) if sigmas[ii] > 1e-15]
    if len(axes) > 0:
        for axis, sigma in axes:
            square_gaussian_filter1d(input, sigma, axis, output,
                              mode, cval)
            input = output
    else:
        output[...] = input[...]
    return return_value
Exemple #7
0
def _correlate_or_convolve(input, weights, output, mode, cval, origin,
                           convolution):
    input = np.asarray(input)
    if np.iscomplexobj(input):
        raise TypeError('Complex type not supported')
    origins = _ni_support._normalize_sequence(origin, input.ndim)
    weights = np.asarray(weights, dtype=np.float64)
    wshape = [ii for ii in weights.shape if ii > 0]
    if len(wshape) != input.ndim:
        raise RuntimeError('filter weights array has incorrect shape.')
    if convolution:
        weights = weights[tuple([slice(None, None, -1)] * weights.ndim)]
        for ii in range(len(origins)):
            origins[ii] = -origins[ii]
            if not weights.shape[ii] & 1:
                origins[ii] -= 1
    for origin, lenw in zip(origins, wshape):
        if _invalid_origin(origin, lenw):
            raise ValueError('Invalid origin; origin must satisfy '
                             '-(weights.shape[k] // 2) <= origin[k] <= '
                             '(weights.shape[k]-1) // 2')

    if not weights.flags.contiguous:
        weights = weights.copy()
    output = _ni_support._get_output(output, input)
    mode = _ni_support._extend_mode_to_code(mode)
    _nd_image.correlate(input, weights, output, mode, cval, origins)
    return output
Exemple #8
0
    def __FilterDataFast(self):
        data = self.data[:, :, 0]
        mode = _ni_support._extend_mode_to_code("reflect")
        # lowpass filter to suppress noise
        output, a = _ni_support._get_output(None, data)
        _nd_image.correlate1d(data, ofdP.weightsLowpass, 0, output, mode, 0, 0)
        _nd_image.correlate1d(output, ofdP.weightsLowpass, 1, output, mode, 0,
                              0)

        # lowpass filter again to find background
        output, b = _ni_support._get_output(None, data)
        _nd_image.correlate1d(data, ofdP.weightsHighpass, 0, output, mode, 0,
                              0)
        _nd_image.correlate1d(output, ofdP.weightsHighpass, 1, output, mode, 0,
                              0)

        return a - b
Exemple #9
0
def gaussian_filter(input, sigma, order=0, output=None,
                  mode="reflect", cval=0.0, truncate=4.0):
    """Multidimensional Gaussian filter.

    Parameters
    ----------
    %(input)s
    sigma : scalar or sequence of scalars
        Standard deviation for Gaussian kernel. The standard
        deviations of the Gaussian filter are given for each axis as a
        sequence, or as a single number, in which case it is equal for
        all axes.
    order : {0, 1, 2, 3} or sequence from same set, optional
        The order of the filter along each axis is given as a sequence
        of integers, or as a single number.  An order of 0 corresponds
        to convolution with a Gaussian kernel. An order of 1, 2, or 3
        corresponds to convolution with the first, second or third
        derivatives of a Gaussian. Higher order derivatives are not
        implemented
    %(output)s
    %(mode)s
    %(cval)s
    truncate : float
        Truncate the filter at this many standard deviations.
        Default is 4.0.

    Returns
    -------
    gaussian_filter : ndarray
        Returned array of same shape as `input`.

    Notes
    -----
    The multidimensional filter is implemented as a sequence of
    one-dimensional convolution filters. The intermediate arrays are
    stored in the same data type as the output. Therefore, for output
    types with a limited precision, the results may be imprecise
    because intermediate results may be stored with insufficient
    precision.

    """
    input = numpy.asarray(input)
    output, return_value = _ni_support._get_output(output, input)
    orders = _ni_support._normalize_sequence(order, input.ndim)
    if not set(orders).issubset(set(range(4))):
        raise ValueError('Order outside 0..4 not implemented')
    sigmas = _ni_support._normalize_sequence(sigma, input.ndim)
    axes = list(range(input.ndim))
    axes = [(axes[ii], sigmas[ii], orders[ii])
                        for ii in range(len(axes)) if sigmas[ii] > 1e-15]
    if len(axes) > 0:
        for axis, sigma, order in axes:
            gaussian_filter1d(input, sigma, axis, order, output,
                              mode, cval, truncate)
            input = output
    else:
        output[...] = input[...]
    return return_value
Exemple #10
0
def _extract_local_histogram(image,
                             mask=slice(None),
                             bins=19,
                             rang="image",
                             cutoffp=(0.0, 100.0),
                             size=None,
                             footprint=None,
                             output=None,
                             mode="ignore",
                             origin=0):
    """
    Internal, single-image version of @see local_histogram
    
    Note: Values outside of the histograms range are not considered.
    Note: Mode constant is not available, instead a mode "ignore" is provided.
    Note: Default dtype of returned values is float.
    """
    if "constant" == mode:
        raise RuntimeError('boundary mode not supported')
    elif "ignore" == mode:
        mode = "constant"
    if 'image' == rang:
        rang = tuple(numpy.percentile(image[mask], cutoffp))
    elif not 2 == len(rang):
        raise RuntimeError(
            'the rang must contain exactly two elements or the string "image"')

    _, bin_edges = numpy.histogram([], bins=bins, range=rang)
    output, _ = _get_output(numpy.float if None == output else output,
                            image,
                            shape=[bins] + list(image.shape))

    # threshold the image into the histogram bins represented by the output images first dimension, treat last bin separately, since upper border is inclusive
    for i in range(bins - 1):
        output[i] = (image >= bin_edges[i]) & (image < bin_edges[i + 1])
    output[-1] = (image >= bin_edges[-2]) & (image <= bin_edges[-1])

    # apply the sum filter to each dimension, then normalize by dividing through the sum of elements in the bins of each histogram
    for i in range(bins):
        output[i] = sum_filter(output[i],
                               size=size,
                               footprint=footprint,
                               output=None,
                               mode=mode,
                               cval=0.0,
                               origin=origin)
    divident = numpy.sum(output, 0)
    divident[0 == divident] = 1
    output /= divident

    # Notes on modes:
    # mode=constant with a cval outside histogram range for the histogram equals a mode=constant with a cval = 0 for the sum_filter
    # mode=constant with a cval inside  histogram range for the histogram has no equal for the sum_filter (and does not make much sense)
    # mode=X for the histogram equals mode=X for the sum_filter

    # treat as multi-spectral image which intensities to extracted
    return _extract_feature(_extract_intensities, [h for h in output], mask)
def average_filter(input, size=None, footprint=None, output=None, mode="reflect", cval=0.0, origin=0):
    r"""
    Calculates a multi-dimensional average filter.

    Parameters
    ----------
    input : array-like
        input array to filter
    size : scalar or tuple, optional
        See footprint, below
    footprint : array, optional
        Either `size` or `footprint` must be defined. `size` gives
        the shape that is taken from the input array, at every element
        position, to define the input to the filter function.
        `footprint` is a boolean array that specifies (implicitly) a
        shape, but also which of the elements within this shape will get
        passed to the filter function. Thus ``size=(n,m)`` is equivalent
        to ``footprint=np.ones((n,m))``. We adjust `size` to the number
        of dimensions of the input array, so that, if the input array is
        shape (10,10,10), and `size` is 2, then the actual size used is
        (2,2,2).
    output : array, optional
        The ``output`` parameter passes an array in which to store the
        filter output.
    mode : {'reflect','constant','nearest','mirror', 'wrap'}, optional
        The ``mode`` parameter determines how the array borders are
        handled, where ``cval`` is the value when mode is equal to
        'constant'. Default is 'reflect'
    cval : scalar, optional
        Value to fill past edges of input if ``mode`` is 'constant'. Default
        is 0.0
    origin : scalar, optional
        The ``origin`` parameter controls the placement of the filter.
        Default 0

    Returns
    -------
    average_filter : ndarray
        Returned array of same shape as `input`.

    Notes
    -----
    Convenience implementation employing convolve.

    See Also
    --------
    scipy.ndimage.filters.convolve : Convolve an image with a kernel.
    """
    footprint = __make_footprint(input, size, footprint)
    filter_size = footprint.sum()
    
    output = _get_output(output, input)
    sum_filter(input, footprint=footprint, output=output, mode=mode, cval=cval, origin=origin)
    output /= filter_size
    return output
Exemple #12
0
def average_filter(input, size=None, footprint=None, output=None, mode="reflect", cval=0.0, origin=0):
    """
    Calculates a multi-dimensional average filter.

    Parameters
    ----------
    input : array-like
        input array to filter
    size : scalar or tuple, optional
        See footprint, below
    footprint : array, optional
        Either `size` or `footprint` must be defined. `size` gives
        the shape that is taken from the input array, at every element
        position, to define the input to the filter function.
        `footprint` is a boolean array that specifies (implicitly) a
        shape, but also which of the elements within this shape will get
        passed to the filter function. Thus ``size=(n,m)`` is equivalent
        to ``footprint=np.ones((n,m))``. We adjust `size` to the number
        of dimensions of the input array, so that, if the input array is
        shape (10,10,10), and `size` is 2, then the actual size used is
        (2,2,2).
    output : array, optional
        The ``output`` parameter passes an array in which to store the
        filter output.
    mode : {'reflect','constant','nearest','mirror', 'wrap'}, optional
        The ``mode`` parameter determines how the array borders are
        handled, where ``cval`` is the value when mode is equal to
        'constant'. Default is 'reflect'
    cval : scalar, optional
        Value to fill past edges of input if ``mode`` is 'constant'. Default
        is 0.0
    origin : scalar, optional
        The ``origin`` parameter controls the placement of the filter.
        Default 0

    Returns
    -------
    average_filter : ndarray
        Returned array of same shape as `input`.

    Notes
    -----
    Convenience implementation employing convolve.

    See Also
    --------
    convolve : Convolve an image with a kernel.
    """
    footprint = __make_footprint(input, size, footprint)
    filter_size = footprint.sum()
    
    output, return_value = _get_output(output, input)
    sum_filter(input, footprint=footprint, output=output, mode=mode, cval=cval, origin=origin)
    output /= filter_size
    return return_value
Exemple #13
0
def separable_convolution(input,
                          weights,
                          output=None,
                          mode="reflect",
                          cval=0.0,
                          origin=0):
    r"""
    Calculate a n-dimensional convolution of a separable kernel to a n-dimensional input.
    
    Achieved by calling convolution1d along the first axis, obtaining an intermediate
    image, on which the next convolution1d along the second axis is called and so on.
    
    Parameters
    ----------
    input : array_like
        Array of which to estimate the noise.
    weights : ndarray
        One-dimensional sequence of numbers.          
    output : array, optional
        The `output` parameter passes an array in which to store the
        filter output.
    mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional
        The `mode` parameter determines how the array borders are
        handled, where `cval` is the value when mode is equal to
        'constant'. Default is 'reflect'
    cval : scalar, optional
        Value to fill past edges of input if `mode` is 'constant'. Default
        is 0.0
    origin : scalar, optional
        The `origin` parameter controls the placement of the filter.
        Default 0.0.
        
    Returns
    -------
    output : ndarray
        Input image convolved with the supplied kernel.
    """
    input = numpy.asarray(input)
    output, return_value = _ni_support._get_output(output, input)
    axes = list(range(input.ndim))
    if len(axes) > 0:
        convolve1d(input, weights, axes[0], output, mode, cval, origin)
        for ii in range(1, len(axes)):
            convolve1d(output, weights, axes[ii], output, mode, cval, origin)
    else:
        output[...] = input[...]
    return return_value
Exemple #14
0
    def Afunc(self, f):
        '''Forward transform - convolve with the PSF'''
        fs = reshape(f, (self.height, self.width, self.depth))

        #d = ndimage.gaussian_filter(fs, self.sigma)
        mode = _ni_support._extend_mode_to_code("reflect")
        #lowpass filter to suppress noise
        #a = ndimage.gaussian_filter(data.astype('f4'), self.filterRadiusLowpass)
        #print data.shape

        output, a = _ni_support._get_output(None, fs)
        _nd_image.correlate1d(fs, self.kernel, 0, output, mode, 0,0)
        _nd_image.correlate1d(output, self.kernel, 1, output, mode, 0,0)
        
        #ndimage.uniform_filter(output, self.oversamp, output=output)

        #d = real(d);
        return ravel(output)#[::oversamp,::oversamp,:])
Exemple #15
0
    def Afunc(self, f):
        """Forward transform - convolve with the PSF"""
        fs = np.reshape(f, (self.height, self.width, self.depth))

        #d = ndimage.gaussian_filter(fs, self.sigma)
        mode = _ni_support._extend_mode_to_code("reflect")
        #lowpass filter to suppress noise
        #a = ndimage.gaussian_filter(data.astype('f4'), self.filterRadiusLowpass)
        #print data.shape

        output, a = _ni_support._get_output(None, fs)
        _nd_image.correlate1d(fs, self.kernel, 0, output, mode, 0, 0)
        _nd_image.correlate1d(output, self.kernel, 1, output, mode, 0, 0)

        #ndimage.uniform_filter(output, self.oversamp, output=output)

        #d = real(d);
        return np.ravel(output)  #[::oversamp,::oversamp,:])
Exemple #16
0
def sinc_filter(input, sigma, order=0, output=None,
                    mode="reflect", cval=0.0, truncate=6.0):
    input = np.asarray(input)
    output = _ni_support._get_output(output, input)
    orders = _ni_support._normalize_sequence(order, input.ndim)
    sigmas = _ni_support._normalize_sequence(sigma, input.ndim)
    modes = _ni_support._normalize_sequence(mode, input.ndim)
    axes = list(range(input.ndim))
    axes = [(axes[ii], sigmas[ii], orders[ii], modes[ii])
            for ii in range(len(axes)) if sigmas[ii] > 1e-15]
    if len(axes) > 0:
        for axis, sigma, order, mode in axes:
            sinc_filter1d(input, sigma, axis, order, output,
                              mode, cval, truncate)
            input = output
    else:
        output[...] = input[...]
    return output
Exemple #17
0
def separable_convolution(input, weights, output=None, mode="reflect", cval=0.0, origin=0):
    r"""
    Calculate a n-dimensional convolution of a separable kernel to a n-dimensional input.
    
    Achieved by calling convolution1d along the first axis, obtaining an intermediate
    image, on which the next convolution1d along the second axis is called and so on.
    
    Parameters
    ----------
    input : array_like
        Array of which to estimate the noise.
    weights : ndarray
        One-dimensional sequence of numbers.          
    output : array, optional
        The `output` parameter passes an array in which to store the
        filter output.
    mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional
        The `mode` parameter determines how the array borders are
        handled, where `cval` is the value when mode is equal to
        'constant'. Default is 'reflect'
    cval : scalar, optional
        Value to fill past edges of input if `mode` is 'constant'. Default
        is 0.0
    origin : scalar, optional
        The `origin` parameter controls the placement of the filter.
        Default 0.0.
        
    Returns
    -------
    output : ndarray
        Input image convolved with the supplied kernel.
    """
    input = numpy.asarray(input)
    output, return_value = _ni_support._get_output(output, input)
    axes = list(range(input.ndim))
    if len(axes) > 0:
        convolve1d(input, weights, axes[0], output, mode, cval, origin)
        for ii in range(1, len(axes)):
            convolve1d(output, weights, axes[ii], output, mode, cval, origin)
    else:
        output[...] = input[...]
    return return_value
    
    
Exemple #18
0
def _extract_local_histogram(image, mask=slice(None), bins=19, rang="image", cutoffp=(0.0, 100.0), size=None, footprint=None, output=None, mode="ignore", origin=0):
    """
    Internal, single-image version of @see local_histogram
    
    Note: Values outside of the histograms range are not considered.
    Note: Mode constant is not available, instead a mode "ignore" is provided.
    Note: Default dtype of returned values is float.
    """
    if "constant" == mode:
        raise RuntimeError('boundary mode not supported')
    elif "ignore" == mode:
        mode = "constant"
    if 'image' == rang:
        rang = tuple(numpy.percentile(image[mask], cutoffp))
    elif not 2 == len(rang):
        raise RuntimeError('the rang must contain exactly two elements or the string "image"')
        
    _, bin_edges = numpy.histogram([], bins=bins, range=rang)
    output, _ = _get_output(numpy.float if None == output else output, image, shape = [bins] + list(image.shape))

    # threshold the image into the histogram bins represented by the output images first dimension, treat last bin separately, since upper border is inclusive
    for i in range(bins - 1):
        output[i] = (image >= bin_edges[i]) & (image < bin_edges[i + 1])
    output[-1] = (image >= bin_edges[-2]) & (image <= bin_edges[-1])

    # apply the sum filter to each dimension, then normalize by dividing through the sum of elements in the bins of each histogram
    for i in range(bins):
        output[i] = sum_filter(output[i], size=size, footprint=footprint, output=None, mode=mode, cval=0.0, origin=origin)
    divident = numpy.sum(output, 0)
    divident[0 == divident] = 1
    output /= divident
    
    # Notes on modes:
    # mode=constant with a cval outside histogram range for the histogram equals a mode=constant with a cval = 0 for the sum_filter
    # mode=constant with a cval inside  histogram range for the histogram has no equal for the sum_filter (and does not make much sense)
    # mode=X for the histogram equals mode=X for the sum_filter

    # treat as multi-spectral image which intensities to extracted
    return _extract_feature(_extract_intensities, [h for h in output], mask)
Exemple #19
0
def map_coordinates_parallel(input,
                             coordinates,
                             output=None,
                             order=3,
                             mode='constant',
                             cval=0.0,
                             prefilter=True,
                             chunklen=None,
                             threads=None):
    """

    Parallalized version of `scipy.ndimage.map_coordinates`.

    `scipy.ndimage.map_coordinates` is slow for large datasets. Speed improvement can be
    achieved by

     * Splitting the data into chunks
     * Performing the transformation of chunks in parallel

    New parameters:

    chunklen: Size of the chunks in pixels per axis. Default: None
        Special values:
            None: Automatic (Chooses a default based on number of dimensions)
            0: Do not split data into chunks. (implicitly sets threads==1)

    threads: Number of threads. Default: None
        None: Automatic (One thread per available processing unit)

    """

    # this part is taken without change from scipy's serial implementation
    if order < 0 or order > 5:
        raise RuntimeError('spline order not supported')
    input = np.asarray(input)
    if np.iscomplexobj(input):
        raise TypeError('Complex type not supported')
    coordinates = np.asarray(coordinates)
    if np.iscomplexobj(coordinates):
        raise TypeError('Complex type not supported')
    output_shape = coordinates.shape[1:]
    if input.ndim < 1 or len(output_shape) < 1:
        raise RuntimeError('input and output rank must be > 0')
    if coordinates.shape[0] != input.ndim:
        raise RuntimeError('invalid shape for coordinate array')
    mode = _ni_support._extend_mode_to_code(mode)
    if prefilter and order > 1:
        filtered = spline_filter(input, order, output=np.float64)
    else:
        filtered = input

    # return value of `_ni_support._get_output` changed between scipy versions, code here is
    # adapted to work with both
    output = _ni_support._get_output(output, input, shape=output_shape)
    retval = output
    if isinstance(output, tuple):
        output, retval = output

    # below here there is the new code for splitting into chunks and parallel execution
    if chunklen is None:
        # set defaults
        chunklen = 128
        if output.ndim < 3:
            chunklen = 1024

    def chunk_arguments(filtered, coordinates, output):
        chunks = []
        for axis in range(output.ndim):
            chunkstarts = np.arange(0, output.shape[axis], chunklen)
            chunkends = chunkstarts + chunklen
            chunkends[-1] = output.shape[axis]
            chunks.append([
                slice(start, stop)
                for start, stop in zip(chunkstarts, chunkends)
            ])

        for chunk in itertools.product(*chunks):
            sub_coordinates = coordinates[(slice(None), ) + chunk].copy()
            filtered_region = []
            for in_axis in range(filtered.ndim):
                c = sub_coordinates[in_axis, ...]
                cmin = max(0, int(np.floor(np.min(c))) - 5)
                cmax = min(filtered.shape[in_axis],
                           int(np.ceil(np.max(c))) + 5)
                sub_coordinates[in_axis, ...] -= cmin
                filtered_region.append(slice(cmin, cmax))
            sub_filtered = filtered[tuple(filtered_region)]
            sub_output = output[chunk]

            yield (sub_filtered, sub_coordinates, sub_output)

    def map_coordinates_chunk(arg):
        sub_filtered, sub_coordinates, sub_output = arg
        _nd_image.geometric_transform(sub_filtered, None, sub_coordinates,
                                      None, None, sub_output, order, mode,
                                      cval, None, None)

    if chunklen > 0:
        list_of_chunk_args = list(
            chunk_arguments(filtered, coordinates, output))
    else:
        list_of_chunk_args = [(filtered, coordinates, output)]

    if len(list_of_chunk_args) == 1:
        threads = 1

    if threads != 1:
        threadpool = ThreadPoolExecutor(threads)
        my_map = threadpool.map
    else:
        my_map = map

    # execution happens here
    list(my_map(map_coordinates_chunk, list_of_chunk_args))

    if threads != 1:
        if have_concurrent_futures:
            threadpool.shutdown()
        else:
            threadpool.close()
            threadpool.join()

    return retval
def immerkaer_local(input, size, output=None, mode="reflect", cval=0.0):
    r"""
    Estimate the local noise.
    
    The input image is assumed to have additive zero mean Gaussian noise. The Immerkaer
    noise estimation is applied to the image locally over a N-dimensional cube of
    side-length size. The size of the region should be sufficiently high for a stable
    noise estimation.
    
    Parameters
    ----------
    input : array_like
        Array of which to estimate the noise.
    size : integer
        The local region's side length.
    output : ndarray, optional
        The `output` parameter passes an array in which to store the
        filter output.        
    mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional
        The `mode` parameter determines how the array borders are
        handled, where `cval` is the value when mode is equal to
        'constant'. Default is 'reflect'
    cval : scalar, optional
        Value to fill past edges of input if `mode` is 'constant'. Default
        is 0.0        
        
    Returns
    -------
    sigmas : array_like
        Map of the estimated standard deviation of the images Gaussian noise per voxel.
    
    Notes
    -----
    Does not take the voxel spacing into account.
    Works good with medium to strong noise. Tends to underestimate for low noise levels.
    
    See also
    --------
    immerkaer
    """
    output = _ni_support._get_output(output, input)
    footprint = numpy.asarray([1] * size)
    
    # build nd-kernel to acquire square root of sum of squared elements
    kernel = [1, -2, 1]
    for _ in range(input.ndim - 1):
        kernel = numpy.tensordot(kernel, [1, -2, 1], 0)
    divider = numpy.square(numpy.abs(kernel)).sum() # 36 for 1d, 216 for 3D, etc.
    
    # compute laplace of input
    laplace = separable_convolution(input, [1, -2, 1], numpy.double, mode, cval)
    
    # compute factor
    factor = numpy.sqrt(numpy.pi / 2.) * 1. / ( numpy.sqrt(divider) * numpy.power(footprint.size, laplace.ndim) )
    
    # locally sum laplacian values
    separable_convolution(numpy.abs(laplace), footprint, output, mode, cval)
    
    output *= factor
    
    return output
Exemple #21
0
def zoom(input, zoom, output=None, order=3, mode='constant', cval=0.0,
         prefilter=True):
    """
    Zoom an array.

    The array is zoomed using spline interpolation of the requested order.

    Parameters
    ----------
    input : ndarray
        The input array.
    zoom : float or sequence, optional
        The zoom factor along the axes. If a float, `zoom` is the same for each
        axis. If a sequence, `zoom` should contain one value for each axis.
    output : ndarray or dtype, optional
        The array in which to place the output, or the dtype of the returned
        array.
    order : int, optional
        The order of the spline interpolation, default is 3.
        The order has to be in the range 0-5.
    mode : str, optional
        Points outside the boundaries of the input are filled according
        to the given mode ('constant', 'nearest', 'reflect' or 'wrap').
        Default is 'constant'.
    cval : scalar, optional
        Value used for points outside the boundaries of the input if
        ``mode='constant'``. Default is 0.0
    prefilter : bool, optional
        The parameter prefilter determines if the input is pre-filtered with
        `spline_filter` before interpolation (necessary for spline
        interpolation of order > 1).  If False, it is assumed that the input is
        already filtered. Default is True.

    Returns
    -------
    return_value : ndarray or None
        The zoomed input. If `output` is given as a parameter, None is
        returned.

    """
    if order < 0 or order > 5:
        raise RuntimeError('spline order not supported')
    input = numpy.asarray(input)
    if numpy.iscomplexobj(input):
        raise TypeError('Complex type not supported')
    if input.ndim < 1:
        raise RuntimeError('input and output rank must be > 0')
    mode = _extend_mode_to_code(mode)
    if prefilter and order > 1:
        filtered = spline_filter(input, order, output = numpy.float64)
    else:
        filtered = input
    zoom = _ni_support._normalize_sequence(zoom, input.ndim)
    output_shape = tuple([int(ii * jj) for ii, jj in zip(input.shape, zoom)])

    zoom_div = numpy.array(output_shape, float)
    zoom = (numpy.array(input.shape)) / zoom_div

    # Zooming to non-finite values in unpredictable, so just choose
    # zoom factor 1 instead
    zoom[~numpy.isfinite(zoom)] = 1

    output, return_value = _ni_support._get_output(output, input,
                                                   shape=output_shape)
    zoom = numpy.asarray(zoom, dtype = numpy.float64)
    zoom = numpy.ascontiguousarray(zoom)
    _nd_image.zoom_shift(filtered, zoom, None, output, order, mode, cval)
    return return_value
Exemple #22
0
def map_coordinates_parallel(input, coordinates, output=None, order=3, mode='constant', cval=0.0,
                             prefilter=True, chunklen=None, threads=None):
    """

    Parallalized version of `scipy.ndimage.map_coordinates`.

    `scipy.ndimage.map_coordinates` is slow for large datasets. Speed improvement can be
    achieved by

     * Splitting the data into chunks
     * Performing the transformation of chunks in parallel

    New parameters:

    chunklen: Size of the chunks in pixels per axis. Default: None
        Special values:
            None: Automatic (Chooses a default based on number of dimensions)
            0: Do not split data into chunks. (implicitly sets threads==1)

    threads: Number of threads. Default: None
        None: Automatic (One thread per available processing unit)

    """

    # this part is taken without change from scipy's serial implementation
    if order < 0 or order > 5:
        raise RuntimeError('spline order not supported')
    input = np.asarray(input)
    if np.iscomplexobj(input):
        raise TypeError('Complex type not supported')
    coordinates = np.asarray(coordinates)
    if np.iscomplexobj(coordinates):
        raise TypeError('Complex type not supported')
    output_shape = coordinates.shape[1:]
    if input.ndim < 1 or len(output_shape) < 1:
        raise RuntimeError('input and output rank must be > 0')
    if coordinates.shape[0] != input.ndim:
        raise RuntimeError('invalid shape for coordinate array')
    mode = _ni_support._extend_mode_to_code(mode)
    if prefilter and order > 1:
        filtered = spline_filter(input, order, output=np.float64)
    else:
        filtered = input

    # return value of `_ni_support._get_output` changed between scipy versions, code here is
    # adapted to work with both
    output = _ni_support._get_output(output, input, shape=output_shape)
    retval = output
    if isinstance(output, tuple):
        output, retval = output

    # below here there is the new code for splitting into chunks and parallel execution
    if chunklen is None:
        # set defaults
        chunklen = 128
        if output.ndim < 3:
            chunklen = 1024

    def chunk_arguments(filtered, coordinates, output):
        chunks = []
        for axis in range(output.ndim):
            chunkstarts = np.arange(0, output.shape[axis], chunklen)
            chunkends = chunkstarts + chunklen
            chunkends[-1] = output.shape[axis]
            chunks.append([slice(start, stop) for start, stop in zip(chunkstarts, chunkends)])

        for chunk in itertools.product(*chunks):
            sub_coordinates = coordinates[(slice(None),) + chunk].copy()
            filtered_region = []
            for in_axis in range(filtered.ndim):
                c = sub_coordinates[in_axis, ...]
                cmin = max(0, int(np.floor(np.min(c)))-5)
                cmax = min(filtered.shape[in_axis], int(np.ceil(np.max(c)))+5)
                sub_coordinates[in_axis, ...] -= cmin
                filtered_region.append(slice(cmin, cmax))
            sub_filtered = filtered[tuple(filtered_region)]
            sub_output = output[chunk]

            yield (sub_filtered, sub_coordinates, sub_output)

    def map_coordinates_chunk(arg):
        sub_filtered, sub_coordinates, sub_output = arg
        _nd_image.geometric_transform(sub_filtered, None, sub_coordinates, None, None,
                                      sub_output, order, mode, cval, None, None)

    if chunklen > 0:
        list_of_chunk_args = list(chunk_arguments(filtered, coordinates, output))
    else:
        list_of_chunk_args = [(filtered, coordinates, output)]

    if len(list_of_chunk_args) == 1:
        threads = 1

    if threads != 1:
        threadpool = ThreadPoolExecutor(threads)
        my_map = threadpool.map
    else:
        my_map = map

    # execution happens here
    list(my_map(map_coordinates_chunk, list_of_chunk_args))

    if threads != 1:
        if have_concurrent_futures:
            threadpool.shutdown()
        else:
            threadpool.close()
            threadpool.join()

    return retval
Exemple #23
0
def pad(input,
        size=None,
        footprint=None,
        output=None,
        mode="reflect",
        cval=0.0):
    r"""
    Returns a copy of the input, padded by the supplied structuring element.
    
    In the case of odd dimensionality, the structure element will be centered as
    following on the currently processed position::
    
        [[T, Tx, T],
         [T, T , T]]
         
    , where Tx denotes the center of the structure element.

    Simulates the behaviour of scipy.ndimage filters.

    Parameters
    ----------
    input : array_like
        Input array to pad.
    size : scalar or tuple, optional
        See footprint, below
    footprint : array, optional
        Either `size` or `footprint` must be defined. `size` gives
        the shape that is taken from the input array, at every element
        position, to define the input to the filter function.
        `footprint` is a boolean array that specifies (implicitly) a
        shape, but also which of the elements within this shape will get
        passed to the filter function. Thus ``size=(n,m)`` is equivalent
        to ``footprint=np.ones((n,m))``. We adjust `size` to the number
        of dimensions of the input array, so that, if the input array is
        shape (10,10,10), and `size` is 2, then the actual size used is
        (2,2,2).
    output : array, optional
        The `output` parameter passes an array in which to store the
        filter output.
    mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional
        The `mode` parameter determines how the array borders are
        handled, where `cval` is the value when mode is equal to
        'constant'. Default is 'reflect'.
    cval : scalar, optional
        Value to fill past edges of input if `mode` is 'constant'. Default
        is 0.0
        
    Returns
    -------
    output : ndarray
        The padded version of the input image.
        
    Notes
    -----
    Since version 1.7.0, numpy supplied a pad function `numpy.pad` that provides
    the same functionality and should be preferred.
    
    Raises
    ------
    ValueError
        If the provided footprint/size is more than double the image size.
    """
    input = numpy.asarray(input)
    if footprint is None:
        if size is None:
            raise RuntimeError("no footprint or filter size provided")
        sizes = _ni_support._normalize_sequence(size, input.ndim)
        footprint = numpy.ones(sizes, dtype=bool)
    else:
        footprint = numpy.asarray(footprint, dtype=bool)
    fshape = [ii for ii in footprint.shape if ii > 0]
    if len(fshape) != input.ndim:
        raise RuntimeError('filter footprint array has incorrect shape.')

    if numpy.any([x > 2 * y for x, y in zip(footprint.shape, input.shape)]):
        raise ValueError(
            'The size of the padding element is not allowed to be more than double the size of the input array in any dimension.'
        )

    padding_offset = [((s - 1) / 2, s / 2) for s in fshape]
    input_slicer = [
        slice(l, None if 0 == r else -1 * r) for l, r in padding_offset
    ]
    output_shape = [s + sum(os) for s, os in zip(input.shape, padding_offset)]
    output, return_value = _ni_support._get_output(output, input, output_shape)

    if 'constant' == mode:
        output += cval
        output[input_slicer] = input
        return return_value
    elif 'nearest' == mode:
        output[input_slicer] = input
        dim_mult_slices = [
            (d, l, slice(None, l), slice(l, l + 1))
            for d, (l, _) in zip(list(range(output.ndim)), padding_offset)
            if not 0 == l
        ]
        dim_mult_slices.extend([
            (d, r, slice(-1 * r, None), slice(-2 * r, -2 * r + 1))
            for d, (_, r) in zip(list(range(output.ndim)), padding_offset)
            if not 0 == r
        ])
        for dim, mult, to_slice, from_slice in dim_mult_slices:
            slicer_to = [
                to_slice if d == dim else slice(None)
                for d in range(output.ndim)
            ]
            slicer_from = [
                from_slice if d == dim else slice(None)
                for d in range(output.ndim)
            ]
            if not 0 == mult:
                output[slicer_to] = numpy.concatenate([output[slicer_from]] *
                                                      mult, dim)
        return return_value
    elif 'mirror' == mode:
        dim_slices = [
            (d, slice(None, l), slice(l + 1, 2 * l + 1))
            for d, (l, _) in zip(list(range(output.ndim)), padding_offset)
            if not 0 == l
        ]
        dim_slices.extend([
            (d, slice(-1 * r, None), slice(-2 * r - 1, -1 * r - 1))
            for d, (_, r) in zip(list(range(output.ndim)), padding_offset)
            if not 0 == r
        ])
        reverse_slice = slice(None, None, -1)
    elif 'reflect' == mode:
        dim_slices = [
            (d, slice(None, l), slice(l, 2 * l))
            for d, (l, _) in zip(list(range(output.ndim)), padding_offset)
            if not 0 == l
        ]
        dim_slices.extend([
            (d, slice(-1 * r, None), slice(-2 * r, -1 * r))
            for d, (_, r) in zip(list(range(output.ndim)), padding_offset)
            if not 0 == r
        ])
        reverse_slice = slice(None, None, -1)
    elif 'wrap' == mode:
        dim_slices = [
            (d, slice(None,
                      l), slice(-1 * (l + r), -1 * r if not 0 == r else None))
            for d, (l, r) in zip(list(range(output.ndim)), padding_offset)
            if not 0 == l
        ]
        dim_slices.extend([
            (d, slice(-1 * r, None), slice(l, r + l))
            for d, (l, r) in zip(list(range(output.ndim)), padding_offset)
            if not 0 == r
        ])
        reverse_slice = slice(None)
    else:
        raise RuntimeError('boundary mode not supported')

    output[input_slicer] = input
    for dim, to_slice, from_slice in dim_slices:
        slicer_reverse = [
            reverse_slice if d == dim else slice(None)
            for d in range(output.ndim)
        ]
        slicer_to = [
            to_slice if d == dim else slice(None) for d in range(output.ndim)
        ]
        slicer_from = [
            from_slice if d == dim else slice(None) for d in range(output.ndim)
        ]
        output[slicer_to] = output[slicer_from][slicer_reverse]

    return return_value
Exemple #24
0
def pad(input, size=None, footprint=None, output=None, mode="reflect", cval=0.0):
    """
    Returns a copy of the input, padded by the supplied structuring element.
    
    In the case of odd dimensionality, the structure element will be centered as
    following on the currently processed position:
    [[T, Tx, T],
     [T, T , T]]
    , where Tx denotes the center of the structure element.

    Simulates the behaviour of scipy.ndimage filters.

    input : array_like
        Input array to pad.
    size : scalar or tuple, optional
        See footprint, below
    footprint : array, optional
        Either `size` or `footprint` must be defined. `size` gives
        the shape that is taken from the input array, at every element
        position, to define the input to the filter function.
        `footprint` is a boolean array that specifies (implicitly) a
        shape, but also which of the elements within this shape will get
        passed to the filter function. Thus ``size=(n,m)`` is equivalent
        to ``footprint=np.ones((n,m))``. We adjust `size` to the number
        of dimensions of the input array, so that, if the input array is
        shape (10,10,10), and `size` is 2, then the actual size used is
        (2,2,2).
    output : array, optional
        The `output` parameter passes an array in which to store the
        filter output.
    mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional
        The `mode` parameter determines how the array borders are
        handled, where `cval` is the value when mode is equal to
        'constant'. Default is 'reflect'.
    cval : scalar, optional
        Value to fill past edges of input if `mode` is 'constant'. Default
        is 0.0
    """
    input = numpy.asarray(input)
    if footprint is None:
        if size is None:
            raise RuntimeError("no footprint or filter size provided")
        sizes = _ni_support._normalize_sequence(size, input.ndim)
        footprint = numpy.ones(sizes, dtype=bool)
    else:
        footprint = numpy.asarray(footprint, dtype=bool)
    fshape = [ii for ii in footprint.shape if ii > 0]
    if len(fshape) != input.ndim:
        raise RuntimeError('filter footprint array has incorrect shape.')

    padding_offset = [((s - 1) / 2, s / 2) for s in fshape]
    input_slicer = [slice(l, None if 0 == r else -1 * r) for l, r in padding_offset]
    output_shape = [s + sum(os) for s, os in zip(input.shape, padding_offset)]
    output, return_value = _ni_support._get_output(output, input, output_shape)

    if 'constant' == mode:
        output += cval
        output[input_slicer] = input
        return return_value
    elif 'nearest' == mode:
        output[input_slicer] = input
        dim_mult_slices = [(d, l, slice(None, l), slice(l, l + 1)) for d, (l, _) in zip(range(output.ndim), padding_offset) if not 0 == l]
        dim_mult_slices.extend([(d, r, slice(-1 * r, None), slice(-2 * r, -2 * r + 1)) for d, (_, r) in zip(range(output.ndim), padding_offset) if not 0 == r])
        for dim, mult, to_slice, from_slice in dim_mult_slices:
            slicer_to = [to_slice if d == dim else slice(None) for d in range(output.ndim)]
            slicer_from = [from_slice if d == dim else slice(None) for d in range(output.ndim)]
            if not 0 == mult:
                output[slicer_to] = numpy.concatenate([output[slicer_from]] * mult, dim)
        return return_value
    elif 'mirror' == mode:
        dim_slices = [(d, slice(None, l), slice(l + 1, 2 * l + 1)) for d, (l, _) in zip(range(output.ndim), padding_offset) if not 0 == l]
        dim_slices.extend([(d, slice(-1 * r, None), slice(-2 * r - 1, -1 * r - 1)) for d, (_, r) in zip(range(output.ndim), padding_offset) if not 0 == r])
        reverse_slice = slice(None, None, -1)
    elif 'reflect' == mode:
        dim_slices = [(d, slice(None, l), slice(l, 2 * l)) for d, (l, _) in zip(range(output.ndim), padding_offset) if not 0 == l]
        dim_slices.extend([(d, slice(-1 * r, None), slice(-2 * r, -1 * r)) for d, (_, r) in zip(range(output.ndim), padding_offset) if not 0 == r])
        reverse_slice = slice(None, None, -1)
    elif 'wrap' == mode:
        dim_slices = [(d, slice(None, l), slice(-1 * (l + r), -1 * r if not 0 == r else None)) for d, (l, r) in zip(range(output.ndim), padding_offset) if not 0 == l]
        dim_slices.extend([(d, slice(-1 * r, None), slice(l, r + l)) for d, (l, r) in zip(range(output.ndim), padding_offset) if not 0 == r])
        reverse_slice = slice(None)
    else:
        raise RuntimeError('boundary mode not supported')
    
    output[input_slicer] = input
    for dim, to_slice, from_slice in dim_slices:
        slicer_reverse = [reverse_slice if d == dim else slice(None) for d in range(output.ndim)]
        slicer_to = [to_slice if d == dim else slice(None) for d in range(output.ndim)]
        slicer_from = [from_slice if d == dim else slice(None) for d in range(output.ndim)]
        output[slicer_to] = output[slicer_from][slicer_reverse]

    return return_value
Exemple #25
0
def immerkaer_local(input, size, output=None, mode="reflect", cval=0.0):
    r"""
    Estimate the local noise.
    
    The input image is assumed to have additive zero mean Gaussian noise. The Immerkaer
    noise estimation is applied to the image locally over a N-dimensional cube of
    side-length size. The size of the region should be sufficiently high for a stable
    noise estimation.
    
    Parameters
    ----------
    input : array_like
        Array of which to estimate the noise.
    size : integer
        The local region's side length.
    output : ndarray, optional
        The `output` parameter passes an array in which to store the
        filter output.        
    mode : {'reflect', 'constant', 'nearest', 'mirror', 'wrap'}, optional
        The `mode` parameter determines how the array borders are
        handled, where `cval` is the value when mode is equal to
        'constant'. Default is 'reflect'
    cval : scalar, optional
        Value to fill past edges of input if `mode` is 'constant'. Default
        is 0.0        
        
    Returns
    -------
    sigmas : array_like
        Map of the estimated standard deviation of the images Gaussian noise per voxel.
    
    Notes
    -----
    Does not take the voxel spacing into account.
    Works good with medium to strong noise. Tends to underestimate for low noise levels.
    
    See also
    --------
    immerkaer
    """
    output, return_value = _ni_support._get_output(output, input)
    footprint = numpy.asarray([1] * size)
    
    # build nd-kernel to acquire square root of sum of squared elements
    kernel = [1, -2, 1]
    for _ in range(input.ndim - 1):
        kernel = numpy.tensordot(kernel, [1, -2, 1], 0)
    divider = numpy.square(numpy.abs(kernel)).sum() # 36 for 1d, 216 for 3D, etc.
    
    # compute laplace of input
    laplace = separable_convolution(input, [1, -2, 1], numpy.double, mode, cval)
    
    # compute factor
    factor = numpy.sqrt(numpy.pi / 2.) * 1. / ( numpy.sqrt(divider) * numpy.power(footprint.size, laplace.ndim) )
    
    # locally sum laplacian values
    separable_convolution(numpy.abs(laplace), footprint, output, mode, cval)
    
    output *= factor
    
    return return_value