Example #1
0
def check_type(stochastic):
    """
    type, shape = check_type(stochastic)

    Checks the type of a stochastic's value. Output value 'type' may be
    bool, int, float, or complex. Nonnative numpy dtypes are lumped into
    these categories. Output value 'shape' is () if the stochastic's value
    is scalar, or a nontrivial tuple otherwise.
    """
    val = stochastic.value
    if val.__class__ is bool:
        return bool, ()
    elif val.__class__ in [int, uint, long, byte, short, intc, int_, longlong, intp, ubyte, ushort, uintc, uint, ulonglong, uintp]:
        return int, ()
    elif val.__class__ in [float, single, float_, longfloat]:
        return float, ()
    elif val.__class__ in [complex, csingle, complex_, clongfloat]:
        return complex, ()
    elif isinstance(val, ndarray):
        if obj2sctype(val) is bool_:
            return bool, val.shape
        elif obj2sctype(val) in [byte, short, intc, int_, longlong, intp, ubyte, ushort, uintc, uint, ulonglong, uintp]:
            return int, val.shape
        elif obj2sctype(val) in [single, float_, longfloat]:
            return float, val.shape
        elif obj2sctype(val) in [csingle, complex_, clongfloat]:
            return complex, val.shape
    else:
        return 'object', ()
Example #2
0
def check_type(stochastic):
    """
    type, shape = check_type(stochastic)

    Checks the type of a stochastic's value. Output value 'type' may be
    bool, int, float, or complex. Nonnative numpy dtypes are lumped into
    these categories. Output value 'shape' is () if the stochastic's value
    is scalar, or a nontrivial tuple otherwise.
    """
    val = stochastic.value
    
    if val.__class__ in bool_dtypes:
        return bool, ()
    elif val.__class__ in integer_dtypes:
        return int, ()
    elif val.__class__ in float_dtypes:
        return float, ()
    elif val.__class__ in complex_dtypes:
        return complex, ()
    elif isinstance(val, ndarray):
        if obj2sctype(val) in bool_dtypes:
            return bool, val.shape
        elif obj2sctype(val) in integer_dtypes:
            return int, val.shape
        elif obj2sctype(val) in float_dtypes:
            return float, val.shape
        elif obj2sctype(val) in complex_dtypes:
            return complex, val.shape
        else:
            return 'object', val.shape
    else:
        return 'object', ()
Example #3
0
def print_coercion_table(ntypes, inputfirstvalue, inputsecondvalue, firstarray):
    print '+',
    for char in ntypes: print char,
    print
    for row in ntypes:
        if row == 'O':
            rowtype = GenericObject
        else:
            rowtype = np.obj2sctype(row)

        print row,
        for col in ntypes:
            if col == 'O':
                coltype = GenericObject
            else:
                coltype = np.obj2sctype(col)
            try:
                if firstarray:
                    rowvalue = np.array([rowtype(inputfirstvalue)], dtype=rowtype)
                else:
                    rowvalue = rowtype(inputfirstvalue)
                colvalue = coltype(inputsecondvalue)
                value = np.add(rowvalue,colvalue)
                if isinstance(value, np.ndarray):
                    char = value.dtype.char
                else:
                    char = np.dtype(type(value)).char
            except ValueError:
                char = '!'
            except OverflowError:
                char = '@'
            except TypeError:
                char = '#'
            print char,
        print
Example #4
0
    def test_floating_exceptions(self):
        """Test basic arithmetic function errors"""
        oldsettings = np.seterr(all='raise')
        try:
            # Test for all real and complex float types
            for typecode in np.typecodes['AllFloat']:
                ftype = np.obj2sctype(typecode)
                if np.dtype(ftype).kind == 'f':
                    # Get some extreme values for the type
                    fi = np.finfo(ftype)
                    ft_tiny = fi.tiny
                    ft_max = fi.max
                    ft_eps = fi.eps
                    underflow = 'underflow'
                    divbyzero = 'divide by zero'
                else:
                    # 'c', complex, corresponding real dtype
                    rtype = type(ftype(0).real)
                    fi = np.finfo(rtype)
                    ft_tiny = ftype(fi.tiny)
                    ft_max = ftype(fi.max)
                    ft_eps = ftype(fi.eps)
                    # The complex types raise different exceptions
                    underflow = ''
                    divbyzero = ''
                overflow = 'overflow'
                invalid = 'invalid'

                self.assert_raises_fpe(underflow,
                        lambda a,b:a/b, ft_tiny, ft_max)
                self.assert_raises_fpe(underflow,
                        lambda a,b:a*b, ft_tiny, ft_tiny)
                self.assert_raises_fpe(overflow,
                        lambda a,b:a*b, ft_max, ftype(2))
                self.assert_raises_fpe(overflow,
                        lambda a,b:a/b, ft_max, ftype(0.5))
                self.assert_raises_fpe(overflow,
                        lambda a,b:a+b, ft_max, ft_max*ft_eps)
                self.assert_raises_fpe(overflow,
                        lambda a,b:a-b, -ft_max, ft_max*ft_eps)
                self.assert_raises_fpe(overflow,
                        np.power, ftype(2), ftype(2**fi.nexp))
                self.assert_raises_fpe(divbyzero,
                        lambda a,b:a/b, ftype(1), ftype(0))
                self.assert_raises_fpe(invalid,
                        lambda a,b:a/b, ftype(np.inf), ftype(np.inf))
                self.assert_raises_fpe(invalid,
                        lambda a,b:a/b, ftype(0), ftype(0))
                self.assert_raises_fpe(invalid,
                        lambda a,b:a-b, ftype(np.inf), ftype(np.inf))
                self.assert_raises_fpe(invalid,
                        lambda a,b:a+b, ftype(np.inf), ftype(-np.inf))
                self.assert_raises_fpe(invalid,
                        lambda a,b:a*b, ftype(0), ftype(np.inf))
        finally:
            np.seterr(**oldsettings)
Example #5
0
 def update_from_dict(self, level, data_d):
     if len(data_d) > 0:
         dtype = numpy.dtype(
             {'names': list(data_d.keys()),
              'formats': list(numpy.obj2sctype(v)
                              for v in list(data_d.values()))
              })
         self.update_from_array(level,
                                numpy.array([tuple(list(data_d.values()))],
                                            dtype=dtype))
Example #6
0
def complex_type(scalar_type):
    """
    Determine the complex type corresponding to a component scalar type.
    """
    scalar_type = np.obj2sctype(scalar_type)
    if scalar_type == np.single:
        return np.csingle
    elif scalar_type == np.float_:
        return np.complex_
    elif scalar_type == np.longfloat:
        return np.clongfloat
    else:
        raise ValueError('Invalid scalar_type: {0}.'.format(scalar_type))
Example #7
0
def scalar_type(complex_type):
    """
    Determine the type of the real and imaginary parts of a complex type.
    """
    complex_type = np.obj2sctype(complex_type)
    if complex_type == np.csingle:
        return np.single
    elif complex_type == np.complex_:
        return np.float_
    elif complex_type == np.clongfloat:
        return np.longfloat
    else:
        raise ValueError('Invalid complex_type: {0}.'.format(complex_type))
Example #8
0
def get_dtype(obj):
    '''
    Helper function to return the `numpy.dtype` of an arbitrary object.

    Parameters
    ----------
    obj : object
        Any object (but typically some kind of number or array).

    Returns
    -------
    dtype : `numpy.dtype`
        The type of the given object.
    '''
    if hasattr(obj, 'dtype'):
        return obj.dtype
    else:
        return np.obj2sctype(type(obj))
Example #9
0
	def init(self, z,y,x,t,d,
	         k, focus=0, bandlimit=0,mask=None,
			 dtype=numpy.complex64, itype=numpy.int32,
			 ss_w=2, ss_v=1, ss_u=2, cutoff=1e-2,
			 ):

		self.init_empty_arrays()

		if not isinstance(focus, numpy.ndarray) or focus.size==1:
			focus = focus*numpy.ones(t.shape, numpy.obj2sctype(focus))

		self.z, self.y, self.x = z, y, x
		self.t, self.d = t, d
		self.k, self.bandlimit, self.focus, self.mask = k, bandlimit, focus, mask
		self.dtype, self.itype = dtype, itype
		self.ss_w, self.ss_v, self.ss_u, self.cutoff = ss_w, ss_v, ss_u, cutoff

		self._estimate_size_only = False

		return self
Example #10
0
    def test_floating_exceptions_power(self):
        """Test basic arithmetic function errors"""
        oldsettings = np.seterr(all='raise')
        try:
            # Test for all real and complex float types
            for typecode in np.typecodes['AllFloat']:
                ftype = np.obj2sctype(typecode)
                if np.dtype(ftype).kind == 'f':
                    # Get some extreme values for the type
                    fi = np.finfo(ftype)
                else:
                    # 'c', complex, corresponding real dtype
                    rtype = type(ftype(0).real)
                    fi = np.finfo(rtype)
                overflow = 'overflow'

                self.assert_raises_fpe(overflow,
                        np.power, ftype(2), ftype(2**fi.nexp))
        finally:
            np.seterr(**oldsettings)
import numpy as np

np.obj2sctype(np.int32)
np.obj2sctype(np.array([1., 2.]))
np.obj2sctype(np.array([1.j]))
np.obj2sctype(dict)
np.obj2sctype('string')
np.obj2sctype(1, default=list)
Example #12
0
def convert(image, dtype, force_copy=False, uniform=False):
    """
    Convert an image to the requested data-type.

    Warnings are issued in case of precision loss, or when negative values
    are clipped during conversion to unsigned integer types (sign loss).

    Floating point values are expected to be normalized and will be clipped
    to the range [0.0, 1.0] or [-1.0, 1.0] when converting to unsigned or
    signed integers respectively.

    Numbers are not shifted to the negative side when converting from
    unsigned to signed integer types. Negative values will be clipped when
    converting to unsigned integers.

    Parameters
    ----------
    image : ndarray
        Input image.
    dtype : dtype
        Target data-type.
    force_copy : bool, optional
        Force a copy of the data, irrespective of its current dtype.
    uniform : bool, optional
        Uniformly quantize the floating point range to the integer range.
        By default (uniform=False) floating point values are scaled and
        rounded to the nearest integers, which minimizes back and forth
        conversion errors.
    """
    image = np.asarray(image)
    dtypeobj_in = image.dtype
    dtypeobj_out = np.dtype(dtype)
    dtype_in = dtypeobj_in.type
    dtype_out = dtypeobj_out.type
    kind_in = dtypeobj_in.kind
    kind_out = dtypeobj_out.kind
    itemsize_in = dtypeobj_in.itemsize
    itemsize_out = dtypeobj_out.itemsize

    # Below, we do an `issubdtype` check.  Its purpose is to find out
    # whether we can get away without doing any image conversion.  This happens
    # when:
    #
    # - the output and input dtypes are the same or
    # - when the output is specified as a type, and the input dtype
    #   is a subclass of that type (e.g. `np.floating` will allow
    #   `float32` and `float64` arrays through)

    if np.issubdtype(dtype_in, np.obj2sctype(dtype)):
        if force_copy:
            image = image.copy()
        return image

    if not (dtype_in in _supported_types and dtype_out in _supported_types):
        raise ValueError("Can not convert from {} to {}.".format(
            dtypeobj_in, dtypeobj_out))

    if kind_in in 'ui':
        imin_in = np.iinfo(dtype_in).min
        imax_in = np.iinfo(dtype_in).max
    if kind_out in 'ui':
        imin_out = np.iinfo(dtype_out).min
        imax_out = np.iinfo(dtype_out).max

    # any -> binary
    if kind_out == 'b':
        return image > dtype_in(dtype_range[dtype_in][1] / 2)

    # binary -> any
    if kind_in == 'b':
        result = image.astype(dtype_out)
        if kind_out != 'f':
            result *= dtype_out(dtype_range[dtype_out][1])
        return result

    # float -> any
    if kind_in == 'f':
        if kind_out == 'f':
            # float -> float
            return image.astype(dtype_out)

        if np.min(image) < -1.0 or np.max(image) > 1.0:
            raise ValueError("Images of type float must be between -1 and 1.")
        # floating point -> integer
        # use float type that can represent output integer type
        computation_type = _dtype_itemsize(itemsize_out, dtype_in, np.float32,
                                           np.float64)

        if not uniform:
            if kind_out == 'u':
                image_out = np.multiply(image,
                                        imax_out,
                                        dtype=computation_type)
            else:
                image_out = np.multiply(image, (imax_out - imin_out) / 2,
                                        dtype=computation_type)
                image_out -= 1.0 / 2.
            np.rint(image_out, out=image_out)
            np.clip(image_out, imin_out, imax_out, out=image_out)
        elif kind_out == 'u':
            image_out = np.multiply(image,
                                    imax_out + 1,
                                    dtype=computation_type)
            np.clip(image_out, 0, imax_out, out=image_out)
        else:
            image_out = np.multiply(image, (imax_out - imin_out + 1.0) / 2.0,
                                    dtype=computation_type)
            np.floor(image_out, out=image_out)
            np.clip(image_out, imin_out, imax_out, out=image_out)
        return image_out.astype(dtype_out)

    # signed/unsigned int -> float
    if kind_out == 'f':
        # use float type that can exactly represent input integers
        computation_type = _dtype_itemsize(itemsize_in, dtype_out, np.float32,
                                           np.float64)

        if kind_in == 'u':
            # using np.divide or np.multiply doesn't copy the data
            # until the computation time
            image = np.multiply(image, 1. / imax_in, dtype=computation_type)
            # DirectX uses this conversion also for signed ints
            # if imin_in:
            #     np.maximum(image, -1.0, out=image)
        else:
            image = np.add(image, 0.5, dtype=computation_type)
            image *= 2 / (imax_in - imin_in)

        return np.asarray(image, dtype_out)

    # unsigned int -> signed/unsigned int
    if kind_in == 'u':
        if kind_out == 'i':
            # unsigned int -> signed int
            image = _scale(image, 8 * itemsize_in, 8 * itemsize_out - 1)
            return image.view(dtype_out)
        else:
            # unsigned int -> unsigned int
            return _scale(image, 8 * itemsize_in, 8 * itemsize_out)

    # signed int -> unsigned int
    if kind_out == 'u':
        image = _scale(image, 8 * itemsize_in - 1, 8 * itemsize_out)
        result = np.empty(image.shape, dtype_out)
        np.maximum(image, 0, out=result, dtype=image.dtype, casting='unsafe')
        return result

    # signed int -> signed int
    if itemsize_in > itemsize_out:
        return _scale(image, 8 * itemsize_in - 1, 8 * itemsize_out - 1)

    image = image.astype(_dtype_bits('i', itemsize_out * 8))
    image -= imin_in
    image = _scale(image, 8 * itemsize_in, 8 * itemsize_out, copy=False)
    image += imin_out
    return image.astype(dtype_out)
Example #13
0
def _convert(image, dtype, force_copy=False, uniform=False):
    """
    Adapted from: https://github.com/scikit-image/scikit-image/blob/main/skimage/util/dtype.py#L510-L531
    
    Convert an image to the requested data-type.
    Warnings are issued in case of precision loss, or when negative values
    are clipped during conversion to unsigned integer types (sign loss).
    Floating point values are expected to be normalized and will be clipped
    to the range [0.0, 1.0] or [-1.0, 1.0] when converting to unsigned or
    signed integers respectively.
    Numbers are not shifted to the negative side when converting from
    unsigned to signed integer types. Negative values will be clipped when
    converting to unsigned integers.
    Parameters
    ----------
    image : ndarray
        Input image.
    dtype : dtype
        Target data-type.
    force_copy : bool, optional
        Force a copy of the data, irrespective of its current dtype.
    uniform : bool, optional
        Uniformly quantize the floating point range to the integer range.
        By default (uniform=False) floating point values are scaled and
        rounded to the nearest integers, which minimizes back and forth
        conversion errors.
    .. versionchanged :: 0.15
        ``_convert`` no longer warns about possible precision or sign
        information loss. See discussions on these warnings at:
        https://github.com/scikit-image/scikit-image/issues/2602
        https://github.com/scikit-image/scikit-image/issues/543#issuecomment-208202228
        https://github.com/scikit-image/scikit-image/pull/3575
    References
    ----------
    .. [1] DirectX data conversion rules.
           https://msdn.microsoft.com/en-us/library/windows/desktop/dd607323%28v=vs.85%29.aspx
    .. [2] Data Conversions. In "OpenGL ES 2.0 Specification v2.0.25",
           pp 7-8. Khronos Group, 2010.
    .. [3] Proper treatment of pixels as integers. A.W. Paeth.
           In "Graphics Gems I", pp 249-256. Morgan Kaufmann, 1990.
    .. [4] Dirty Pixels. J. Blinn. In "Jim Blinn's corner: Dirty Pixels",
           pp 47-57. Morgan Kaufmann, 1998.
    """
    dtype_range = {bool: (False, True),
                np.bool_: (False, True),
                np.bool8: (False, True),
                float: (-1, 1),
                np.float_: (-1, 1),
                np.float16: (-1, 1),
                np.float32: (-1, 1),
                np.float64: (-1, 1)}

    def _dtype_itemsize(itemsize, *dtypes):
        """Return first of `dtypes` with itemsize greater than `itemsize`
        Parameters
        ----------
        itemsize: int
            The data type object element size.
        Other Parameters
        ----------------
        *dtypes:
            Any Object accepted by `np.dtype` to be converted to a data
            type object
        Returns
        -------
        dtype: data type object
            First of `dtypes` with itemsize greater than `itemsize`.
        """
        return next(dt for dt in dtypes if np.dtype(dt).itemsize >= itemsize)

    def _dtype_bits(kind, bits, itemsize=1):
        """Return dtype of `kind` that can store a `bits` wide unsigned int
        Parameters:
        kind: str
            Data type kind.
        bits: int
            Desired number of bits.
        itemsize: int
            The data type object element size.
        Returns
        -------
        dtype: data type object
            Data type of `kind` that can store a `bits` wide unsigned int
        """

        s = next(i for i in (itemsize, ) + (2, 4, 8) if
                bits < (i * 8) or (bits == (i * 8) and kind == 'u'))

        return np.dtype(kind + str(s))


    def _scale(a, n, m, copy=True):
        """Scale an array of unsigned/positive integers from `n` to `m` bits.
        Numbers can be represented exactly only if `m` is a multiple of `n`.
        Parameters
        ----------
        a : ndarray
            Input image array.
        n : int
            Number of bits currently used to encode the values in `a`.
        m : int
            Desired number of bits to encode the values in `out`.
        copy : bool, optional
            If True, allocates and returns new array. Otherwise, modifies
            `a` in place.
        Returns
        -------
        out : array
            Output image array. Has the same kind as `a`.
        """
        kind = a.dtype.kind
        if n > m and a.max() < 2 ** m:
            mnew = int(np.ceil(m / 2) * 2)
            if mnew > m:
                dtype = "int{}".format(mnew)
            else:
                dtype = "uint{}".format(mnew)
            n = int(np.ceil(n / 2) * 2)
            return a.astype(_dtype_bits(kind, m))
        elif n == m:
            return a.copy() if copy else a
        elif n > m:
            # downscale with precision loss
            if copy:
                b = np.empty(a.shape, _dtype_bits(kind, m))
                np.floor_divide(a, 2**(n - m), out=b, dtype=a.dtype,
                                casting='unsafe')
                return b
            else:
                a //= 2**(n - m)
                return a
        elif m % n == 0:
            # exact upscale to a multiple of `n` bits
            if copy:
                b = np.empty(a.shape, _dtype_bits(kind, m))
                np.multiply(a, (2**m - 1) // (2**n - 1), out=b, dtype=b.dtype)
                return b
            else:
                a = a.astype(_dtype_bits(kind, m, a.dtype.itemsize), copy=False)
                a *= (2**m - 1) // (2**n - 1)
                return a
        else:
            # upscale to a multiple of `n` bits,
            # then downscale with precision loss
            o = (m // n + 1) * n
            if copy:
                b = np.empty(a.shape, _dtype_bits(kind, o))
                np.multiply(a, (2**o - 1) // (2**n - 1), out=b, dtype=b.dtype)
                b //= 2**(o - m)
                return b
            else:
                a = a.astype(_dtype_bits(kind, o, a.dtype.itemsize), copy=False)
                a *= (2**o - 1) // (2**n - 1)
                a //= 2**(o - m)
                return a

    image = np.asarray(image)
    dtypeobj_in = image.dtype
    if dtype is np.floating:
        dtypeobj_out = np.dtype('float64')
    else:
        dtypeobj_out = np.dtype(dtype)
    dtype_in = dtypeobj_in.type
    dtype_out = dtypeobj_out.type
    kind_in = dtypeobj_in.kind
    kind_out = dtypeobj_out.kind
    itemsize_in = dtypeobj_in.itemsize
    itemsize_out = dtypeobj_out.itemsize

    # Below, we do an `issubdtype` check.  Its purpose is to find out
    # whether we can get away without doing any image conversion.  This happens
    # when:
    #
    # - the output and input dtypes are the same or
    # - when the output is specified as a type, and the input dtype
    #   is a subclass of that type (e.g. `np.floating` will allow
    #   `float32` and `float64` arrays through)

    if np.issubdtype(dtype_in, np.obj2sctype(dtype)):
        if force_copy:
            image = image.copy()
        return image

    if kind_in in 'ui':
        imin_in = np.iinfo(dtype_in).min
        imax_in = np.iinfo(dtype_in).max
    if kind_out in 'ui':
        imin_out = np.iinfo(dtype_out).min
        imax_out = np.iinfo(dtype_out).max

    # any -> binary
    if kind_out == 'b':
        return image > dtype_in(dtype_range[dtype_in][1] / 2)

    # binary -> any
    if kind_in == 'b':
        result = image.astype(dtype_out)
        if kind_out != 'f':
            result *= dtype_out(dtype_range[dtype_out][1])
        return result


    # float -> any
    if kind_in == 'f':
        if kind_out == 'f':
            # float -> float
            return image.astype(dtype_out)

        if np.min(image) < -1.0 or np.max(image) > 1.0:
            raise ValueError("Images of type float must be between -1 and 1.")
        # floating point -> integer
        # use float type that can represent output integer type
        computation_type = _dtype_itemsize(itemsize_out, dtype_in,
                                           np.float32, np.float64)

        if not uniform:
            if kind_out == 'u':
                image_out = np.multiply(image, imax_out,
                                        dtype=computation_type)
            else:
                image_out = np.multiply(image, (imax_out - imin_out) / 2,
                                        dtype=computation_type)
                image_out -= 1.0 / 2.
            np.rint(image_out, out=image_out)
            np.clip(image_out, imin_out, imax_out, out=image_out)
        elif kind_out == 'u':
            image_out = np.multiply(image, imax_out + 1,
                                    dtype=computation_type)
            np.clip(image_out, 0, imax_out, out=image_out)
        else:
            image_out = np.multiply(image, (imax_out - imin_out + 1.0) / 2.0,
                                    dtype=computation_type)
            np.floor(image_out, out=image_out)
            np.clip(image_out, imin_out, imax_out, out=image_out)
        return image_out.astype(dtype_out)

    # signed/unsigned int -> float
    if kind_out == 'f':
        # use float type that can exactly represent input integers
        computation_type = _dtype_itemsize(itemsize_in, dtype_out,
                                           np.float32, np.float64)

        if kind_in == 'u':
            # using np.divide or np.multiply doesn't copy the data
            # until the computation time
            image = np.multiply(image, 1. / imax_in,
                                dtype=computation_type)
            # DirectX uses this conversion also for signed ints
            # if imin_in:
            #     np.maximum(image, -1.0, out=image)
        else:
            image = np.add(image, 0.5, dtype=computation_type)
            image *= 2 / (imax_in - imin_in)

        return np.asarray(image, dtype_out)

    # unsigned int -> signed/unsigned int
    if kind_in == 'u':
        if kind_out == 'i':
            # unsigned int -> signed int
            image = _scale(image, 8 * itemsize_in, 8 * itemsize_out - 1)
            return image.view(dtype_out)
        else:
            # unsigned int -> unsigned int
            return _scale(image, 8 * itemsize_in, 8 * itemsize_out)

    # signed int -> unsigned int
    if kind_out == 'u':
        image = _scale(image, 8 * itemsize_in - 1, 8 * itemsize_out)
        result = np.empty(image.shape, dtype_out)
        np.maximum(image, 0, out=result, dtype=image.dtype, casting='unsafe')
        return result

    # signed int -> signed int
    if itemsize_in > itemsize_out:
        return _scale(image, 8 * itemsize_in - 1, 8 * itemsize_out - 1)

    image = image.astype(_dtype_bits('i', itemsize_out * 8))
    image -= imin_in
    image = _scale(image, 8 * itemsize_in, 8 * itemsize_out, copy=False)
    image += imin_out
    return image.astype(dtype_out)
Example #14
0
def _convert(image, dtype, force_copy=False, uniform=False):
    """
    Convert an image to the requested data-type.

    Warnings are issued in case of precision loss, or when negative values
    are clipped during conversion to unsigned integer types (sign loss).

    Floating point values are expected to be normalized and will be clipped
    to the range [0.0, 1.0] or [-1.0, 1.0] when converting to unsigned or
    signed integers respectively.

    Numbers are not shifted to the negative side when converting from
    unsigned to signed integer types. Negative values will be clipped when
    converting to unsigned integers.

    Parameters
    ----------
    image : ndarray
        Input image.
    dtype : dtype
        Target data-type.
    force_copy : bool, optional
        Force a copy of the data, irrespective of its current dtype.
    uniform : bool, optional
        Uniformly quantize the floating point range to the integer range.
        By default (uniform=False) floating point values are scaled and
        rounded to the nearest integers, which minimizes back and forth
        conversion errors.

    .. versionchanged:: 0.15
        ``_convert`` no longer warns about possible precision or sign
        information loss. See discussions on these warnings at:
        https://github.com/scikit-image/scikit-image/issues/2602
        https://github.com/scikit-image/scikit-image/issues/543#issuecomment-208202228
        https://github.com/scikit-image/scikit-image/pull/3575

    References
    ----------
    .. [1] DirectX data conversion rules.
           https://msdn.microsoft.com/en-us/library/windows/desktop/dd607323%28v=vs.85%29.aspx
    .. [2] Data Conversions. In "OpenGL ES 2.0 Specification v2.0.25",
           pp 7-8. Khronos Group, 2010.
    .. [3] Proper treatment of pixels as integers. A.W. Paeth.
           In "Graphics Gems I", pp 249-256. Morgan Kaufmann, 1990.
    .. [4] Dirty Pixels. J. Blinn. In "Jim Blinn's corner: Dirty Pixels",
           pp 47-57. Morgan Kaufmann, 1998.

    """
    image = np.asarray(image)
    dtypeobj_in = image.dtype
    if dtype is np.floating:
        dtypeobj_out = np.dtype('float64')
    else:
        dtypeobj_out = np.dtype(dtype)
    dtype_in = dtypeobj_in.type
    dtype_out = dtypeobj_out.type
    kind_in = dtypeobj_in.kind
    kind_out = dtypeobj_out.kind
    itemsize_in = dtypeobj_in.itemsize
    itemsize_out = dtypeobj_out.itemsize

    # Below, we do an `issubdtype` check.  Its purpose is to find out
    # whether we can get away without doing any image conversion.  This happens
    # when:
    #
    # - the output and input dtypes are the same or
    # - when the output is specified as a type, and the input dtype
    #   is a subclass of that type (e.g. `np.floating` will allow
    #   `float32` and `float64` arrays through)

    if np.issubdtype(dtype_in, np.obj2sctype(dtype)):
        if force_copy:
            image = image.copy()
        return image

    if not (dtype_in in _supported_types and dtype_out in _supported_types):
        raise ValueError(f'Cannot convert from {dtypeobj_in} to '
                         f'{dtypeobj_out}.')

    if kind_in in 'ui':
        imin_in = np.iinfo(dtype_in).min
        imax_in = np.iinfo(dtype_in).max
    if kind_out in 'ui':
        imin_out = np.iinfo(dtype_out).min
        imax_out = np.iinfo(dtype_out).max

    # any -> binary
    if kind_out == 'b':
        return image > dtype_in(dtype_range[dtype_in][1] / 2)

    # binary -> any
    if kind_in == 'b':
        result = image.astype(dtype_out)
        if kind_out != 'f':
            result *= dtype_out(dtype_range[dtype_out][1])
        return result

    # float -> any
    if kind_in == 'f':
        if kind_out == 'f':
            # float -> float
            return image.astype(dtype_out)

        if np.min(image) < -1.0 or np.max(image) > 1.0:
            raise ValueError("Images of type float must be between -1 and 1.")
        # floating point -> integer
        # use float type that can represent output integer type
        computation_type = _dtype_itemsize(itemsize_out, dtype_in,
                                           np.float32, np.float64)

        if not uniform:
            if kind_out == 'u':
                image_out = np.multiply(image, imax_out,
                                        dtype=computation_type)
            else:
                image_out = np.multiply(image, (imax_out - imin_out) / 2,
                                        dtype=computation_type)
                image_out -= 1.0 / 2.
            np.rint(image_out, out=image_out)
            np.clip(image_out, imin_out, imax_out, out=image_out)
        elif kind_out == 'u':
            image_out = np.multiply(image, imax_out + 1,
                                    dtype=computation_type)
            np.clip(image_out, 0, imax_out, out=image_out)
        else:
            image_out = np.multiply(image, (imax_out - imin_out + 1.0) / 2.0,
                                    dtype=computation_type)
            np.floor(image_out, out=image_out)
            np.clip(image_out, imin_out, imax_out, out=image_out)
        return image_out.astype(dtype_out)

    # signed/unsigned int -> float
    if kind_out == 'f':
        # use float type that can exactly represent input integers
        computation_type = _dtype_itemsize(itemsize_in, dtype_out,
                                           np.float32, np.float64)

        if kind_in == 'u':
            # using np.divide or np.multiply doesn't copy the data
            # until the computation time
            image = np.multiply(image, 1. / imax_in,
                                dtype=computation_type)
            # DirectX uses this conversion also for signed ints
            # if imin_in:
            #     np.maximum(image, -1.0, out=image)
        elif kind_in == 'i':
            # From DirectX conversions:
            # The most negative value maps to -1.0f
            # Every other value is converted to a float (call it c)
            # and then result = c * (1.0f / (2⁽ⁿ⁻¹⁾-1)).

            image = np.multiply(image, 1. / imax_in,
                                dtype=computation_type)
            np.maximum(image, -1.0, out=image)

        else:
            image = np.add(image, 0.5, dtype=computation_type)
            image *= 2 / (imax_in - imin_in)

        return np.asarray(image, dtype_out)

    # unsigned int -> signed/unsigned int
    if kind_in == 'u':
        if kind_out == 'i':
            # unsigned int -> signed int
            image = _scale(image, 8 * itemsize_in, 8 * itemsize_out - 1)
            return image.view(dtype_out)
        else:
            # unsigned int -> unsigned int
            return _scale(image, 8 * itemsize_in, 8 * itemsize_out)

    # signed int -> unsigned int
    if kind_out == 'u':
        image = _scale(image, 8 * itemsize_in - 1, 8 * itemsize_out)
        result = np.empty(image.shape, dtype_out)
        np.maximum(image, 0, out=result, dtype=image.dtype, casting='unsafe')
        return result

    # signed int -> signed int
    if itemsize_in > itemsize_out:
        return _scale(image, 8 * itemsize_in - 1, 8 * itemsize_out - 1)

    image = image.astype(_dtype_bits('i', itemsize_out * 8))
    image -= imin_in
    image = _scale(image, 8 * itemsize_in, 8 * itemsize_out, copy=False)
    image += imin_out
    return image.astype(dtype_out)
Example #15
0
def _convert(image, dtype, force_copy=False, uniform=False):
    """ Convert an image to the requested data-type.
    """

    image = np.asarray(image)
    dtypeobj_in = image.dtype
    dtypeobj_out = np.dtype(dtype)
    dtype_in = dtypeobj_in.type
    dtype_out = dtypeobj_out.type
    kind_in = dtypeobj_in.kind
    kind_out = dtypeobj_out.kind
    itemsize_in = dtypeobj_in.itemsize
    itemsize_out = dtypeobj_out.itemsize

    # Below, we do an `issubdtype` check.  Its purpose is to find out
    # whether we can get away without doing any image conversion.  This happens
    # when:
    #
    # - the output and input dtypes are the same or
    # - when the output is specified as a type, and the input dtype
    #   is a subclass of that type (e.g. `np.floating` will allow
    #   `float32` and `float64` arrays through)

    if np.issubdtype(dtype_in, np.obj2sctype(dtype)):
        if force_copy:
            image = image.copy()
        return image

    if not (dtype_in in _supported_types and dtype_out in _supported_types):
        raise ValueError("Can not convert from {} to {}.".format(
            dtypeobj_in, dtypeobj_out))

    if kind_in in 'ui':
        imin_in = np.iinfo(dtype_in).min
        imax_in = np.iinfo(dtype_in).max
    if kind_out in 'ui':
        imin_out = np.iinfo(dtype_out).min
        imax_out = np.iinfo(dtype_out).max

    # any -> binary
    if kind_out == 'b':
        return image > dtype_in(dtype_range[dtype_in][1] / 2)

    # binary -> any
    if kind_in == 'b':
        result = image.astype(dtype_out)
        if kind_out != 'f':
            result *= dtype_out(dtype_range[dtype_out][1])
        return result

    # float -> any
    if kind_in == 'f':
        if kind_out == 'f':
            # float -> float
            return image.astype(dtype_out)

        if np.min(image) < -1.0 or np.max(image) > 1.0:
            raise ValueError("Images of type float must be between -1 and 1.")
        # floating point -> integer
        # use float type that can represent output integer type
        computation_type = _dtype_itemsize(itemsize_out, dtype_in, np.float32,
                                           np.float64)

        if not uniform:
            if kind_out == 'u':
                image_out = np.multiply(image,
                                        imax_out,
                                        dtype=computation_type)
            else:
                image_out = np.multiply(image, (imax_out - imin_out) / 2,
                                        dtype=computation_type)
                image_out -= 1.0 / 2.
            np.rint(image_out, out=image_out)
            np.clip(image_out, imin_out, imax_out, out=image_out)
        elif kind_out == 'u':
            image_out = np.multiply(image,
                                    imax_out + 1,
                                    dtype=computation_type)
            np.clip(image_out, 0, imax_out, out=image_out)
        else:
            image_out = np.multiply(image, (imax_out - imin_out + 1.0) / 2.0,
                                    dtype=computation_type)
            np.floor(image_out, out=image_out)
            np.clip(image_out, imin_out, imax_out, out=image_out)
        return image_out.astype(dtype_out)

    # signed/unsigned int -> float
    if kind_out == 'f':
        # use float type that can exactly represent input integers
        computation_type = _dtype_itemsize(itemsize_in, dtype_out, np.float32,
                                           np.float64)

        if kind_in == 'u':
            # using np.divide or np.multiply doesn't copy the data
            # until the computation time
            image = np.multiply(image, 1. / imax_in, dtype=computation_type)
            # DirectX uses this conversion also for signed ints
            # if imin_in:
            #     np.maximum(image, -1.0, out=image)
        else:
            image = np.add(image, 0.5, dtype=computation_type)
            image *= 2 / (imax_in - imin_in)

        return np.asarray(image, dtype_out)

    # unsigned int -> signed/unsigned int
    if kind_in == 'u':
        if kind_out == 'i':
            # unsigned int -> signed int
            image = _scale(image, 8 * itemsize_in, 8 * itemsize_out - 1)
            return image.view(dtype_out)
        else:
            # unsigned int -> unsigned int
            return _scale(image, 8 * itemsize_in, 8 * itemsize_out)

    # signed int -> unsigned int
    if kind_out == 'u':
        image = _scale(image, 8 * itemsize_in - 1, 8 * itemsize_out)
        result = np.empty(image.shape, dtype_out)
        np.maximum(image, 0, out=result, dtype=image.dtype, casting='unsafe')
        return result

    # signed int -> signed int
    if itemsize_in > itemsize_out:
        return _scale(image, 8 * itemsize_in - 1, 8 * itemsize_out - 1)

    image = image.astype(_dtype_bits('i', itemsize_out * 8))
    image -= imin_in
    image = _scale(image, 8 * itemsize_in, 8 * itemsize_out, copy=False)
    image += imin_out
    return image.astype(dtype_out)
Example #16
0
    def __init__(self, shape, dtype_in=None, data_in=None,
                 overwrite=True, inverse=True, packed=True, use_pyfftw=True):
        try:
            nx, ny, nz = shape
        except (TypeError, ValueError):
            raise ValueError('Expected 3D shape.')
        if nx % 2 or ny % 2 or nz % 2:
            raise ValueError('All shape dimensions must be even.')

        if data_in is not None:
            if not isinstance(data_in, np.ndarray):
                raise ValueError(
                    'Invalid type for data_in: {0}.'.format(type(data_in)))
            dtype_in = data_in.dtype
        # Convert dtype_in to an object in the numpy scalar type hierarchy.
        dtype_in = np.obj2sctype(dtype_in)
        if dtype_in is None:
            raise ValueError('Invalid dtype_in: {0}.'.format(dtype_in))

        # Determine the input and output array type and shape.
        if packed:
            if inverse:
                shape_in = (nx, ny, nz//2 + 1)
                if not issubclass(dtype_in, np.complexfloating):
                    raise ValueError(
                        'Invalid dtype_in for inverse packed transform ' +
                        '(should be complex): {0}.'.format(dtype_in))
                dtype_out = scalar_type(dtype_in)
                shape_out = (nx, ny, nz + 2) if overwrite else shape
            else:
                shape_in = (nx, ny, nz + 2) if overwrite else shape
                if not issubclass(dtype_in, np.floating):
                    raise ValueError(
                        'Invalid dtype_in for forward packed transform ' +
                        '(should be floating): {0}.'.format(dtype_in))
                dtype_out = complex_type(dtype_in)
                shape_out = (nx, ny, nz//2 + 1)
        else:
            if not issubclass(dtype_in, np.complexfloating):
                raise ValueError(
                    'Expected complex dtype_in for transform: {0}.'
                    .format(dtype_in))
            shape_in = shape_out = shape
            dtype_out = dtype_in

        if data_in is not None:
            if data_in.shape != shape_in:
                raise ValueError(
                    'data_in has wrong shape {0}, expected {1}.'
                    .format(data_in.shape, shape_in))
            self.data_in = data_in
            self.nbytes_allocated = 0
        else:
            # Allocate the input and output data buffers.
            self.data_in = allocate(
                shape_in, dtype_in, use_pyfftw=use_pyfftw)
            self.nbytes_allocated = self.data_in.nbytes
        if overwrite:
            if packed:
                # See https://github.com/hgomersall/pyFFTW/issues/29
                self.data_out = self.data_in.view(dtype_out).reshape(shape_out)
                # Hide the padding without copying. See http://www.fftw.org/doc/
                # Multi_002dDimensional-DFTs-of-Real-Data.html.
                if inverse:
                    self.data_out_padded = self.data_out
                    self.data_out = self.data_out[:, :, :nz]
                else:
                    self.data_in_padded = self.data_in
                    self.data_in = self.data_in[:, :, :nz]
            else:
                self.data_out = self.data_in
        else:
            self.data_out = allocate(
                shape_out, dtype_out, use_pyfftw=use_pyfftw)
            self.nbytes_allocated += self.data_out.nbytes

        # Try to use pyFFTW to configure the transform, if requested.
        self.use_pyfftw = use_pyfftw
        if self.use_pyfftw:
            try:
                import pyfftw
                if not pyfftw.is_n_byte_aligned(self.data_in,
                                                pyfftw.simd_alignment):
                    raise ValueError('data_in is not SIMD aligned.')
                if not pyfftw.is_n_byte_aligned(self.data_out,
                                                pyfftw.simd_alignment):
                    raise ValueError('data_out is not SIMD aligned.')
                direction = 'FFTW_BACKWARD' if inverse else 'FFTW_FORWARD'
                self.fftw_plan = pyfftw.FFTW(
                    self.data_in, self.data_out, direction=direction,
                    flags=('FFTW_ESTIMATE',), axes=(0, 1, 2))
                self.fftw_norm = np.float(nx * ny * nz if inverse else 1)
            except ImportError:
                self.use_pyfftw = False

        # Fall back to numpy.fft if we are not using pyFFTW.
        if not self.use_pyfftw:
            if inverse:
                self.transformer = np.fft.irfftn if packed else np.fft.ifftn
            else:
                self.transformer = np.fft.rfftn if packed else np.fft.fftn

        # Remember our options so we can create a reverse plan.
        self.shape = shape
        self.inverse = inverse
        self.packed = packed
        self.overwrite = overwrite
Example #17
0
import numpy as np

reveal_type(np.issctype(np.generic))  # E: bool
reveal_type(np.issctype("foo"))  # E: bool

reveal_type(np.obj2sctype("S8"))  # E: Union[numpy.generic, None]
reveal_type(np.obj2sctype("S8", default=None))  # E: Union[numpy.generic, None]
reveal_type(
    np.obj2sctype("foo",
                  default=int)  # E: Union[numpy.generic, Type[builtins.int*]]
)

reveal_type(np.issubclass_(np.float64, float))  # E: bool
reveal_type(np.issubclass_(np.float64, (int, float)))  # E: bool

reveal_type(np.sctype2char("S8"))  # E: str
reveal_type(np.sctype2char(list))  # E: str

reveal_type(np.find_common_type([np.int64], [np.int64]))  # E: numpy.dtype
Example #18
0
import numpy as np

np.maximum_sctype("S8")
np.maximum_sctype(object)

np.issctype(object)
np.issctype("S8")

np.obj2sctype(list)
np.obj2sctype(list, default=None)
np.obj2sctype(list, default=np.string_)

np.issubclass_(np.int32, int)
np.issubclass_(np.float64, float)
np.issubclass_(np.float64, (int, float))

np.issubsctype("int64", int)
np.issubsctype(np.array([1]), np.array([1]))

np.issubdtype("S1", np.string_)
np.issubdtype(np.float64, np.float32)

np.sctype2char("S1")
np.sctype2char(list)

np.find_common_type([], [np.int64, np.float32, complex])
np.find_common_type((), (np.int64, np.float32, complex))
np.find_common_type([np.int64, np.float32], [])
np.find_common_type([np.float32], [np.int64, np.float64])

np.cast[int]
Example #19
0
def get_dtype(obj):
    if hasattr(obj, 'dtype'):
        return obj.dtype
    else:
        return np.obj2sctype(obj)
Example #20
0
import numpy as np

reveal_type(np.maximum_sctype(np.float64))  # E: Type[{float64}]
reveal_type(np.maximum_sctype("f8"))  # E: Type[Any]

reveal_type(np.issctype(np.float64))  # E: bool
reveal_type(np.issctype("foo"))  # E: Literal[False]

reveal_type(np.obj2sctype(np.float64))  # E: Union[None, Type[{float64}]]
reveal_type(np.obj2sctype(
    np.float64, default=False))  # E: Union[builtins.bool, Type[{float64}]]
reveal_type(np.obj2sctype("S8"))  # E: Union[None, Type[Any]]
reveal_type(np.obj2sctype("S8", default=None))  # E: Union[None, Type[Any]]
reveal_type(np.obj2sctype("foo",
                          default=False))  # E: Union[builtins.bool, Type[Any]]
reveal_type(np.obj2sctype(1))  # E: None
reveal_type(np.obj2sctype(1, default=False))  # E: bool

reveal_type(np.issubclass_(np.float64, float))  # E: bool
reveal_type(np.issubclass_(np.float64, (int, float)))  # E: bool
reveal_type(np.issubclass_(1, 1))  # E: Literal[False]

reveal_type(np.sctype2char("S8"))  # E: str
reveal_type(np.sctype2char(list))  # E: str

reveal_type(np.find_common_type([np.int64], [np.int64]))  # E: numpy.dtype[Any]

reveal_type(np.cast[int])  # E: _CastFunc
reveal_type(np.cast["i8"])  # E: _CastFunc
reveal_type(np.cast[np.int64])  # E: _CastFunc