def fidw(xs, ds, beta=2): '''Interpolate using using U{Inverse Distance Weighting <https://WikiPedia.org/wiki/Inverse_distance_weighting>} (IDW). @arg xs: Known values (C{scalar}[]). @arg ds: Non-negative distances (C{scalar}[]). @kwarg beta: Inverse distance power (C{int}, 0, 1, 2, or 3). @return: Interpolated value C{x} (C{float}). @raise ValueError: Invalid B{C{beta}}, negative B{C{ds}} value, weighted B{C{ds}} below L{EPS} or unequal C{len}C{(}B{C{ds}}C{)} and C{len}C{(}B{C{xs}}C{)}. @note: Using B{C{beta}}C{=0} returns the mean of B{C{xs}}. ''' n, xs = len2(xs) d, ds = len2(ds) if n != d or n < 1: raise LenError(fidw, xs=n, ds=d) d, x = min(zip(ds, xs)) if d > EPS and n > 1: b = -Int_(beta, name=_beta_, low=0, high=3) if b < 0: ds = tuple(d**b for d in ds) d = fsum(ds) if d < EPS: raise _ValueError(ds=d) x = fdot(xs, *ds) / d else: x = fmean(xs) elif d < 0: raise _ValueError(_item_sq('ds', ds.index(d)), d) return x
def fdot3(a, b, c, start=0): '''Return the precision dot product M{start + sum(a[i] * b[i] * c[i] for i=0..len(a))}. @arg a: List, sequence, tuple, etc. (C{scalar}[]). @arg b: List, sequence, tuple, etc. (C{scalar}[]). @arg c: List, sequence, tuple, etc. (C{scalar}[]). @kwarg start: Optional bias (C{scalar}). @return: Dot product (C{float}). @raise LenError: Unequal C{len(B{a})}, C{len(B{b})} and/or C{len(B{c})}. @raise OverflowError: Partial C{2sum} overflow. ''' def _mul3(a, b, c): # map function return a * b * c # PYCHOK returns if not len(a) == len(b) == len(c): raise LenError(fdot3, a=len(a), b=len(b), c=len(c)) if start: f = Fsum(start) return f.fsum(map(_mul3, a, b, c)) else: return fsum(map(_mul3, a, b, c))
def __new__(cls, *args, **name_only): '''New L{_NamedTuple} initialized with B{C{positional}} arguments. @arg args: Tuple items (C{any}), all positional arguments. @kwarg name_only: Only C{B{name}='name'} is used, anu other keyword arguments are I{silently} ignored. @raise LenError: Unequal number of positional arguments and number of item C{_Names_} or C{_Units_}. @raise TypeError: The C{_Names_} or C{_Units_} attribute is not a C{tuple} of at least 2 items. @raise ValueError: Item name is not a C{str} or valid C{identifier} or starts with C{underscore}. ''' self = tuple.__new__(cls, args) if not self._validated: self._validate() n = len(self._Names_) if len(args) != n: raise LenError(self.__class__, args=len(args), _Names_=n) if name_only: # name=NN n = name_only.get(_name_, NN) if n: self.name = n return self
def __init__(self, knots, weight=None, name=NN): '''New L{HeightLSQBiSpline} interpolator. @arg knots: The points with known height (C{LatLon}s). @kwarg weight: Optional weight or weights for each B{C{knot}} (C{scalar} or C{scalar}s). @kwarg name: Optional name for this height interpolator (C{str}). @raise HeightError: Insufficient number of B{C{knots}} or an invalid B{C{knot}} or B{C{weight}}. @raise LenError: Number of B{C{knots}} and B{C{weight}}s don't match. @raise ImportError: Package C{numpy} or C{scipy} not found or not installed. @raise SciPyError: A C{LSQSphereBivariateSpline} issue. @raise SciPyWarning: A C{LSQSphereBivariateSpline} warning as exception. ''' np, spi = self._NumSciPy() xs, ys, hs = self._xyhs3(knots) n = len(hs) w = weight if isscalar(w): w = float(w) if w <= 0: raise HeightError(weight=w) w = [w] * n elif w is not None: m, w = len2(w) if m != n: raise LenError(HeightLSQBiSpline, weight=m, knots=n) w = map2(float, w) m = min(w) if m <= 0: raise HeightError(_item_sq(weight=w.find(m)), m) try: T = 1.0e-4 # like SciPy example ps = np.array(_ordedup(xs, T, PI2 - T)) ts = np.array(_ordedup(ys, T, PI - T)) self._ev = spi.LSQSphereBivariateSpline(ys, xs, hs, ts, ps, eps=EPS, w=w).ev except Exception as x: raise _SciPyIssue(x) if name: self.name = name
def _height(self, lats, lons, Error=HeightError): LLis, d = self._LLis, self.datum if isscalar(lats) and isscalar(lons): llis = LLis(lats, lons, datum=d) else: n, lats = len2(lats) m, lons = len2(lons) if n != m: # format a LenError, but raise an Error e = LenError(self.__class__, lats=n, lons=m, txt=None) raise e if Error is LenError else Error(str(e)) llis = [LLis(*ll, datum=d) for ll in zip(lats, lons)] return self(llis) # __call__(lli) or __call__(llis)
def __new__(cls, *args): '''New L{_NamedTuple} initialized with B{C{positional}} arguments. ''' self = tuple.__new__(cls, args) ns = self._Names_ if not (isinstance(ns, tuple) and len(ns) > 1): # XXX > 0 raise _TypeError(_dot_(self.classname, _Names_), ns) if len(ns) != len(args) or not ns: raise LenError(cls, args=len(args), ns=len(ns)) if _name_ in ns: t = unstr(_dot_(self.classname, _Names_), *ns) raise _NameError(_name_, _name_, txt=t) return self
def fdot(a, *b): '''Return the precision dot product M{sum(a[i] * b[i] for i=0..len(a))}. @arg a: List, sequence, tuple, etc. (C{scalar}s). @arg b: All positional arguments (C{scalar}s). @return: Dot product (C{float}). @raise LenError: Unequal C{len(B{a})} and C{len(B{b})}. @see: Class L{Fdot}. ''' if len(a) != len(b): raise LenError(fdot, a=len(a), b=len(b)) return fsum(map(_mul, a, b))
def __init__(self, a, *b): '''New L{Fdot} precision dot product M{sum(a[i] * b[i] for i=0..len(a))}. @arg a: List, sequence, tuple, etc. (C{scalar}s). @arg b: All positional arguments (C{scalar}s). @raise OverflowError: Partial C{2sum} overflow. @raise LenError: Unequal C{len(B{a})} and C{len(B{b})}. @see: Function L{fdot} and method L{Fsum.fadd}. ''' if len(a) != len(b): raise LenError(Fdot, a=len(a), b=len(b)) Fsum.__init__(self) self.fadd(map(_mul, a, b))
def _validate(self, _OK=False): # see .EcefMatrix '''(INTERNAL) One-time check of C{_Names_} and C{_Units_} for each C{_NamedUnit} I{sub-class separately}. ''' ns = self._Names_ if not (isinstance(ns, tuple) and len(ns) > 1): # XXX > 0 raise _TypeError(_DOT_(self.classname, _Names_), ns) for i, n in enumerate(ns): if not _xvalid(n, _OK=_OK): t = Fmt.SQUARE(_Names_, i) raise _ValueError(_DOT_(self.classname, t), n) us = self._Units_ if not isinstance(us, tuple): raise _TypeError(_DOT_(self.classname, _Units_), us) if len(us) != len(ns): raise LenError(self.__class__, _Units_=len(us), _Names_=len(ns)) for i, u in enumerate(us): if not (u is None or callable(u)): t = Fmt.SQUARE(_Units_, i) raise _TypeError(_DOT_(self.classname, t), u) self.__class__._validated = True