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', ()
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', ()
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
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)
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))
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))
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))
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))
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
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)
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)
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)
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)
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)
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
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
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]
def get_dtype(obj): if hasattr(obj, 'dtype'): return obj.dtype else: return np.obj2sctype(obj)
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