def _init_function(self, r): if isinstance(self.function, str): self.function = self.function.lower() _mapped = { 'inverse': 'inverse_multiquadric', 'inverse multiquadric': 'inverse_multiquadric', 'thin-plate': 'thin_plate' } if self.function in _mapped: self.function = _mapped[self.function] func_name = "_h_" + self.function if hasattr(self, func_name): self._function = getattr(self, func_name) else: functionlist = [ x[3:] for x in dir(self) if x.startswith('_h_') ] raise ValueError("function must be a callable or one of " + ", ".join(functionlist)) self._function = getattr(self, "_h_" + self.function) elif callable(self.function): allow_one = False if hasattr(self.function, 'func_code') or \ hasattr(self.function, '__code__'): val = self.function allow_one = True elif hasattr(self.function, "im_func"): val = get_method_function(self.function) elif hasattr(self.function, "__call__"): val = get_method_function(self.function.__call__) else: raise ValueError( "Cannot determine number of arguments to function") argcount = get_function_code(val).co_argcount if allow_one and argcount == 1: self._function = self.function elif argcount == 2: if sys.version_info[0] >= 3: self._function = self.function.__get__(self, Rbf_poly_bias) else: import new self._function = new.instancemethod( self.function, self, Rbf_poly_bias) else: raise ValueError( "Function argument must take 1 or 2 arguments.") a0 = self._function(r) if a0.shape != r.shape: raise ValueError( "Callable must take array and return array of the same shape") return a0
def _init_function(self, r): if isinstance(self.function, str): self.function = self.function.lower() _mapped = {'inverse': 'inverse_multiquadric', 'inverse multiquadric': 'inverse_multiquadric', 'thin-plate': 'thin_plate'} if self.function in _mapped: self.function = _mapped[self.function] func_name = "_h_" + self.function if hasattr(self, func_name): self._function = getattr(self, func_name) else: functionlist = [x[3:] for x in dir(self) if x.startswith('_h_')] raise ValueError("function must be a callable or one of " + ", ".join(functionlist)) self._function = getattr(self, "_h_"+self.function) elif callable(self.function): allow_one = False if hasattr(self.function, 'func_code') or \ hasattr(self.function, '__code__'): val = self.function allow_one = True elif hasattr(self.function, "im_func"): val = get_method_function(self.function) elif hasattr(self.function, "__call__"): val = get_method_function(self.function.__call__) else: raise ValueError("Cannot determine number of arguments to " "function") argcount = get_function_code(val).co_argcount if allow_one and argcount == 1: self._function = self.function elif argcount == 2: if sys.version_info[0] >= 3: self._function = self.function.__get__(self, Rbf) else: import new self._function = new.instancemethod(self.function, self, Rbf) else: raise ValueError("Function argument must take 1 or 2 " "arguments.") a0 = self._function(r) if a0.shape != r.shape: raise ValueError("Callable must take array and return array of " "the same shape") return a0
class Rbf(object): """ Rbf(*args) A class for radial basis function approximation/interpolation of n-dimensional scattered data. Parameters ---------- *args : arrays x, y, z, ..., d, where x, y, z, ... are the coordinates of the nodes and d is the array of values at the nodes function : str or callable, optional The radial basis function, based on the radius, r, given by the norm (default is Euclidean distance); the default is 'multiquadric':: 'multiquadric': sqrt((r/self.epsilon)**2 + 1) 'inverse': 1.0/sqrt((r/self.epsilon)**2 + 1) 'gaussian': exp(-(r/self.epsilon)**2) 'linear': r 'cubic': r**3 'quintic': r**5 'thin_plate': r**2 * log(r) If callable, then it must take 2 arguments (self, r). The epsilon parameter will be available as self.epsilon. Other keyword arguments passed in will be available as well. epsilon : float, optional Adjustable constant for gaussian or multiquadrics functions - defaults to approximate average distance between nodes (which is a good start). smooth : float, optional Values greater than zero increase the smoothness of the approximation. 0 is for interpolation (default), the function will always go through the nodal points in this case. norm : callable, optional A function that returns the 'distance' between two points, with inputs as arrays of positions (x, y, z, ...), and an output as an array of distance. E.g, the default:: def euclidean_norm(x1, x2): return sqrt( ((x1 - x2)**2).sum(axis=0) ) which is called with x1=x1ndims,newaxis,:] and x2=x2ndims,:,newaxis] such that the result is a matrix of the distances from each point in x1 to each point in x2. Examples -------- >>> from scipy.interpolate import Rbf >>> x, y, z, d = np.random.rand(4, 50) >>> rbfi = Rbf(x, y, z, d) # radial basis function interpolator instance >>> xi = yi = zi = np.linspace(0, 1, 20) >>> di = rbfi(xi, yi, zi) # interpolated values >>> di.shape (20,) """ def _euclidean_norm(self, x1, x2): return np.sqrt(((x1 - x2)**2).sum(axis=0)) def _h_multiquadric(self, r): return np.sqrt((1.0/self.epsilon*r)**2 + 1) def _h_inverse_multiquadric(self, r): return 1.0/np.sqrt((1.0/self.epsilon*r)**2 + 1) def _h_gaussian(self, r): return np.exp(-(1.0/self.epsilon*r)**2) def _h_linear(self, r): return r def _h_cubic(self, r): return r**3 def _h_quintic(self, r): return r**5 def _h_thin_plate(self, r): return xlogy(r**2, r) # Setup self._function and do smoke test on initial r def _init_function(self, r): if isinstance(self.function, str): self.function = self.function.lower() _mapped = {'inverse': 'inverse_multiquadric', 'inverse multiquadric': 'inverse_multiquadric', 'thin-plate': 'thin_plate'} if self.function in _mapped: self.function = _mappedself.function] func_name = "_h_" + self.function if hasattr(self, func_name): self._function = getattr(self, func_name) else: functionlist = x3:] for x in dir(self) if x.startswith('_h_')] raise ValueError("function must be a callable or one of " + ", ".join(functionlist)) self._function = getattr(self, "_h_"+self.function) elif callable(self.function): allow_one = False if hasattr(self.function, 'func_code') or \ hasattr(self.function, '__code__'): val = self.function allow_one = True elif hasattr(self.function, "im_func"): val = get_method_function(self.function) elif hasattr(self.function, "__call__"): val = get_method_function(self.function.__call__) else: raise ValueError("Cannot determine number of arguments to function") argcount = get_function_code(val).co_argcount if allow_one and argcount == 1: self._function = self.function elif argcount == 2: if sys.version_info0] >= 3: self._function = self.function.__get__(self, Rbf) else: import new self._function = new.instancemethod(self.function, self, Rbf)