def one_vec(x, out=None): """The one function, vectorized.""" if is_valid_input_meshgrid(x, self.domain.ndim): out_shape = out_shape_from_meshgrid(x) elif is_valid_input_array(x, self.domain.ndim): out_shape = out_shape_from_array(x) else: raise TypeError('invalid input type') if out is None: return np.ones(out_shape, dtype=self.out_dtype) else: out.fill(1)
def _default_out_of_place(func, dtype, x, **kwargs): """Default in-place evaluation method.""" if is_valid_input_array(x, func.domain.ndim): out_shape = out_shape_from_array(x) elif is_valid_input_meshgrid(x, func.domain.ndim): out_shape = out_shape_from_meshgrid(x) else: raise TypeError('cannot use in-place method to implement ' 'out-of-place non-vectorized evaluation.') if dtype is None: dtype = np.result_type(*x) out = np.empty(out_shape, dtype=dtype) func(x, out=out, **kwargs) return out
def _default_out_of_place(func, x, **kwargs): """Default in-place evaluation method.""" if is_valid_input_array(x, func.domain.ndim): out_shape = out_shape_from_array(x) elif is_valid_input_meshgrid(x, func.domain.ndim): out_shape = out_shape_from_meshgrid(x) else: raise TypeError('cannot use in-place method to implement ' 'out-of-place non-vectorized evaluation') dtype = func.space.out_dtype if dtype is None: dtype = np.result_type(*x) out = np.empty(out_shape, dtype=dtype) func(x, out=out, **kwargs) return out
def __call__(self, x, out=None): """Do the interpolation. Parameters ---------- x : `meshgrid` or `numpy.ndarray` Evaluation points of the interpolator out : `numpy.ndarray`, optional Array to which the results are written. Needs to have correct shape according to input ``x``. Returns ------- out : `numpy.ndarray` Interpolated values. If ``out`` was given, the returned object is a reference to it. """ ndim = len(self.coord_vecs) if self.input_type == 'array': # Make a (1, n) array from one with shape (n,) x = x.reshape([ndim, -1]) out_shape = out_shape_from_array(x) else: if len(x) != ndim: raise ValueError('number of vectors in x is {} instead of ' 'the grid dimension {}' ''.format(len(x), ndim)) out_shape = out_shape_from_meshgrid(x) if out is not None: if not isinstance(out, np.ndarray): raise TypeError('`out` {!r} not a `numpy.ndarray` ' 'instance'.format(out)) if out.shape != out_shape: raise ValueError('output shape {} not equal to expected ' 'shape {}'.format(out.shape, out_shape)) if out.dtype != self.values.dtype: raise ValueError('output dtype {} not equal to expected ' 'dtype {}' ''.format(out.dtype, self.values.dtype)) indices, norm_distances = self._find_indices(x) return self._evaluate(indices, norm_distances, out)
def test_out_shape_from_array(): # 1d arr = np.zeros((1, 1)) assert out_shape_from_array(arr) == (1, ) arr = np.zeros((1, 2)) assert out_shape_from_array(arr) == (2, ) arr = np.zeros((1, )) assert out_shape_from_array(arr) == (1, ) arr = np.zeros((20, )) assert out_shape_from_array(arr) == (20, ) # 3d arr = np.zeros((3, 1)) assert out_shape_from_array(arr) == (1, ) arr = np.zeros((3, 2)) assert out_shape_from_array(arr) == (2, ) arr = np.zeros((3, 20)) assert out_shape_from_array(arr) == (20, )
def test_out_shape_from_array(): # 1d arr = np.zeros((1, 1)) assert out_shape_from_array(arr) == (1,) arr = np.zeros((1, 2)) assert out_shape_from_array(arr) == (2,) arr = np.zeros((1,)) assert out_shape_from_array(arr) == (1,) arr = np.zeros((20,)) assert out_shape_from_array(arr) == (20,) # 3d arr = np.zeros((3, 1)) assert out_shape_from_array(arr) == (1,) arr = np.zeros((3, 2)) assert out_shape_from_array(arr) == (2,) arr = np.zeros((3, 20)) assert out_shape_from_array(arr) == (20,)
def __call__(self, x, out=None, **kwargs): """Evaluate the function at one or multiple values ``x``. Parameters ---------- x : object Input argument for the function evaluation. Conditions on ``x`` depend on vectorization: `False` : ``x`` must be a domain element `True` : ``x`` must be a `numpy.ndarray` with shape ``(d, N)``, where ``d`` is the number of dimensions of the function domain OR ``x`` is a sequence of `numpy.ndarray` with length ``space.ndim``, and the arrays can be broadcast against each other. out : `numpy.ndarray`, optional Output argument holding the result of the function evaluation, can only be used for vectorized functions. Its shape must be equal to ``np.broadcast(*x).shape``. bounds_check : bool Whether or not to check if all input points lie in the function domain. For vectorized evaluation, this requires the domain to implement `Set.contains_all`. Default: `True` Returns ------- out : range element or array of elements Result of the function evaluation. If ``out`` was provided, the returned object is a reference to it. Raises ------ TypeError If ``x`` is not a valid vectorized evaluation argument If ``out`` is not a range element or a `numpy.ndarray` of range elements ValueError If evaluation points fall outside the valid domain """ bounds_check = kwargs.pop('bounds_check', True) if bounds_check and not hasattr(self.domain, 'contains_all'): raise AttributeError('bounds check not possible for ' 'domain {}, missing `contains_all()` ' 'method.'.format(self.domain)) # Check for input type and determine output shape if is_valid_input_array(x, self.domain.ndim): out_shape = out_shape_from_array(x) scalar_out = False # For 1d, squeeze the array if self.domain.ndim == 1 and x.ndim == 2: x = x.squeeze() elif is_valid_input_meshgrid(x, self.domain.ndim): out_shape = out_shape_from_meshgrid(x) scalar_out = False # For 1d, fish out the vector from the tuple if self.domain.ndim == 1: x = x[0] elif x in self.domain: x = np.atleast_2d(x).T # make a (d, 1) array out_shape = (1,) scalar_out = (out is None) else: # Unknown input raise TypeError('argument {!r} not a valid vectorized ' 'input. Expected an element of the domain ' '{dom}, a ({dom.ndim}, n) array ' 'or a length-{dom.ndim} meshgrid sequence.' ''.format(x, dom=self.domain)) # Check bounds if specified if bounds_check: if not self.domain.contains_all(x): raise ValueError('input contains points outside ' 'the domain {}.'.format(self.domain)) # Call the function and check out shape, before or after if out is None: out = self._call(x, **kwargs) if out_shape != (1,) and out.shape != out_shape: raise ValueError('output shape {} not equal to shape ' '{} expected from input.' ''.format(out.shape, out_shape)) else: if not isinstance(out, np.ndarray): raise TypeError('output {!r} not a `numpy.ndarray` ' 'instance.') if out_shape != (1,) and out.shape != out_shape: raise ValueError('output shape {} not equal to shape ' '{} expected from input.' ''.format(out.shape, out_shape)) self._call(x, out=out, **kwargs) # Check output values if bounds_check: if not self.range.contains_all(out): raise ValueError('output contains points outside ' 'the range {}.' ''.format(self.domain)) # Numpy does not implement __complex__ for arrays (in contrast to # __float__), so we have to fish out the scalar ourselves. return self.range.element(out.ravel()[0]) if scalar_out else out
def __call__(self, x, out=None, **kwargs): """Return ``self(x[, out, **kwargs])``. Parameters ---------- x : domain `element-like`, `meshgrid` or `numpy.ndarray` Input argument for the function evaluation. Conditions on ``x`` depend on its type: element-like: must be a castable to a domain element meshgrid: length must be ``space.ndim``, and the arrays must be broadcastable against each other. array: shape must be ``(d, N)``, where ``d`` is the number of dimensions of the function domain out : `numpy.ndarray`, optional Output argument holding the result of the function evaluation, can only be used for vectorized functions. Its shape must be equal to ``np.broadcast(*x).shape``. Other Parameters ---------------- bounds_check : `bool` If `True`, check if all input points lie in the function domain in the case of vectorized evaluation. This requires the domain to implement `Set.contains_all`. Default: `True` Returns ------- out : range element or array of elements Result of the function evaluation. If ``out`` was provided, the returned object is a reference to it. Raises ------ TypeError If ``x`` is not a valid vectorized evaluation argument If ``out`` is not a range element or a `numpy.ndarray` of range elements ValueError If evaluation points fall outside the valid domain """ bounds_check = kwargs.pop('bounds_check', True) if bounds_check and not hasattr(self.domain, 'contains_all'): raise AttributeError('bounds check not possible for ' 'domain {}, missing `contains_all()` ' 'method'.format(self.domain)) if bounds_check and not hasattr(self.range, 'contains_all'): raise AttributeError('bounds check not possible for ' 'range {}, missing `contains_all()` ' 'method'.format(self.range)) ndim = getattr(self.domain, 'ndim', None) # Check for input type and determine output shape if is_valid_input_meshgrid(x, ndim): out_shape = out_shape_from_meshgrid(x) scalar_out = False # Avoid operations on tuples like x * 2 by casting to array if ndim == 1: x = x[0][None, ...] elif is_valid_input_array(x, ndim): x = np.asarray(x) out_shape = out_shape_from_array(x) scalar_out = False # For 1d, squeeze the array if ndim == 1 and x.ndim == 2: x = x.squeeze() elif x in self.domain: x = np.atleast_2d(x).T # make a (d, 1) array out_shape = (1,) scalar_out = (out is None) else: # Unknown input txt_1d = ' or (n,)' if ndim == 1 else '' raise TypeError('Argument {!r} not a valid vectorized ' 'input. Expected an element of the domain ' '{domain}, an array-like with shape ' '({domain.ndim}, n){} or a length-{domain.ndim} ' 'meshgrid tuple.' ''.format(x, txt_1d, domain=self.domain)) # Check bounds if specified if bounds_check: if not self.domain.contains_all(x): raise ValueError('input contains points outside ' 'the domain {}'.format(self.domain)) # Call the function and check out shape, before or after if out is None: if ndim == 1: try: out = self._call(x, **kwargs) if np.ndim(out) == 0 and not scalar_out: # Don't accept scalar result. A typical situation where # this occurs is with comparison operators, e.g. # "return x > 0" which simply gives 'True' for a # non-empty tuple (in Python 2). We raise TypeError # to trigger the call with x[0]. raise TypeError out = np.atleast_1d(np.squeeze(out)) except (TypeError, IndexError): # TypeError is raised if a meshgrid was used but the # function expected an array (1d only). In this case we try # again with the first meshgrid vector. # IndexError is raised in expressions like x[x > 0] since # "x > 0" evaluates to 'True', i.e. 1, and that index is # out of range for a meshgrid tuple of length 1 :-). To get # the real errors with indexing, we check again for the # same scenario (scalar output when not valid) as in the # first case. out = self._call(x[0], **kwargs) if np.ndim(out) == 0 and not scalar_out: raise ValueError('invalid scalar output') out = np.atleast_1d(np.squeeze(out)) else: out = self._call(x, **kwargs) if self.out_dtype is not None: # Cast to proper dtype if needed out = out.astype(self.out_dtype) if out_shape != (1,) and out.shape != out_shape: # Try to broadcast the returned element if possible try: out = np.broadcast_to(out, out_shape) except AttributeError: # The above requires numpy 1.10, fallback impl else shape = [m if n == 1 and m != 1 else 1 for n, m in zip(out.shape, out_shape)] out = out + np.zeros(shape, dtype=out.dtype) else: if not isinstance(out, np.ndarray): raise TypeError('output {!r} not a `numpy.ndarray` ' 'instance') if out_shape != (1,) and out.shape != out_shape: raise ValueError('output shape {} not equal to shape ' '{} expected from input' ''.format(out.shape, out_shape)) if self.out_dtype is not None and out.dtype != self.out_dtype: raise ValueError('`out.dtype` ({}) does not match out_dtype ' '({})'.format(out.dtype, self.out_dtype)) if ndim == 1: # TypeError for meshgrid in 1d, but expected array (see above) try: self._call(x, out=out, **kwargs) except TypeError: self._call(x[0], out=out, **kwargs) else: self._call(x, out=out, **kwargs) # Check output values if bounds_check: if not self.range.contains_all(out): raise ValueError('output contains points outside ' 'the range {}' ''.format(self.range)) # Numpy does not implement __complex__ for arrays (in contrast to # __float__), so we have to fish out the scalar ourselves. return self.range.element(out.ravel()[0]) if scalar_out else out