예제 #1
0
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
예제 #2
0
 def _height(self, lats, lons, Error=HeightError):
     if isscalar(lats) and isscalar(lons):
         llis = LatLon_(lats, lons)
     else:
         n, lats = len2(lats)
         m, lons = len2(lons)
         if n != m:
             raise Error('non-matching %s: %s vs %s' % ('len', n, m))
         llis = [LatLon_(*ll) for ll in zip(lats, lons)]
     return self(llis)  # __call__(lli) or __call__(llis)
예제 #3
0
 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)
예제 #4
0
    def __init__(self, points, tolerance, radius, shortest, indices,
                 **options):
        '''New C{Simplify} state.
        '''
        n, self.pts = len2(points)
        if n > 0:
            self.n = n
            self.r = {0: True, n - 1: True}  # dict to avoid duplicates

        if isNumpy2(points) or isTuple2(points):  # NOT self.pts
            self.subset = points.subset

        if indices:
            self.indices = True

        if radius:
            self.radius = float(radius)
        if self.radius < self.eps:
            raise ValueError('%s too small: %.6e' % ('radius', radius))

        if options:
            self.options = options

        # tolerance converted to degrees squared
        self.s2 = degrees(tolerance / self.radius)**2
        if min(self.s2, tolerance) < self.eps:
            raise ValueError('%s too small: %.6e' % ('tolerance', tolerance))
        self.s2e = self.s2 + 1  # sentinel

        # compute either the shortest or perpendicular distance
        self.d2i = self.d2iS if shortest else self.d2iP  # PYCHOK false
예제 #5
0
    def hypot_(*xs):
        '''Compute the norm M{sqrt(sum(xs[i]**2)) for i=0..len(xs)}.

           @arg xs: X arguments, positional (C{scalar}[]).

           @return: Norm (C{float}).

           @raise OverflowError: Partial C{2sum} overflow.

           @raise ValueError: Invalid or no B{C{xs}} value.

           @see: Similar to Python 3.8+ U{math.hypot
                 <https://docs.Python.org/3.8/library/math.html#math.hypot>},
                 but handling of exceptions, C{nan} and C{infinite} values
                 is different.

           @note: The Python 3.8+ U{math.dist
                  <https://docs.Python.org/3.8/library/math.html#math.dist>}
                  Euclidian distance between 2 I{n}-dimensional points I{p1}
                  and I{p2} can be computed as M{hypot_(*((c1 - c2) for c1,
                  c2 in zip(p1, p2)))}, provided I{p1} and I{p2} have the
                  same, non-zero length I{n}.
        '''
        if xs:
            n, xs = len2(xs)
            if n > 0:
                h = float(max(abs(x) for x in xs))
                if h > 0 and n > 1:
                    X = Fsum(1.0)
                    X.fadd((x / h)**2 for x in xs)
                    h *= sqrt(X.fsum_(-1.0))
                return h
        raise _ValueError(xs=xs, txt=_too_few_)
예제 #6
0
def sumOf(nvectors, Vector=None, h=None, **Vector_kwds):
    '''Return the vectorial sum of two or more n-vectors.

       @arg nvectors: Vectors to be added (C{Nvector}[]).
       @kwarg Vector: Optional class for the vectorial sum (C{Nvector})
                      or C{None}.
       @kwarg h: Optional height, overriding the mean height (C{meter}).
       @kwarg Vector_kwds: Optional, additional B{C{Vector}} keyword
                           arguments, ignored if C{B{Vector}=None}.

       @return: Vectorial sum (B{C{Vector}}) or a L{Vector4Tuple}C{(x, y,
                z, h)} if B{C{Vector}} is C{None}.

       @raise VectorError: No B{C{nvectors}}.
    '''
    n, nvectors = len2(nvectors)
    if n < 1:
        raise VectorError(nvectors=n, txt=MISSING)

    if h is None:
        h = fsum(v.h for v in nvectors) / float(n)

    if Vector is None:
        r = _sumOf(nvectors, Vector=Vector3Tuple).to4Tuple(h)
    else:
        r = _sumOf(nvectors, Vector=Vector, h=h, **Vector_kwds)
    return r
예제 #7
0
    def __init__(self, knots, datum=None, beta=2, wrap=False, name=NN):
        '''New L{HeightIDWkarney} interpolator.

           @arg knots: The points with known height (C{LatLon}s).
           @kwarg datum: Optional datum overriding the default C{Datums.WGS84}
                         and first B{C{knots}}' datum (L{Datum}, L{Ellipsoid},
                         L{Ellipsoid2} or L{a_f2Tuple}).
           @kwarg beta: Inverse distance power (C{int} 1, 2, or 3).
           @kwarg wrap: Wrap and L{unroll180} longitudes (C{bool}).
           @kwarg name: Optional name for this height interpolator (C{str}).

           @raise HeightError: Insufficient number of B{C{knots}} or
                               an invalid B{C{knot}}, B{C{datum}} or
                               B{C{beta}}.

           @raise ImportError: Package U{geographiclib
                  <https://PyPI.org/project/geographiclib>} missing.

           @raise TypeError: Invalid B{C{datum}}.
        '''
        n, self._ks = len2(knots)
        if n < self._kmin:
            raise _insufficientError(self._kmin, knots=n)
        self._datum_setter(datum, self._ks)
        self._Inverse1 = self.datum.ellipsoid.geodesic.Inverse1

        self.beta = beta
        if wrap:
            self._wrap = True
        if name:
            self.name = name
예제 #8
0
    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
예제 #9
0
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 ValueError('%s(%s): %s vs %s' % (fidw.__name, 'len', n, d))

    d, x = min(zip(ds, xs))
    if d > EPS and n > 1:
        b = -int(beta)
        if -4 < b < 0:  # and b == -beta
            ds = tuple(d**b for d in ds)
            d = fsum(ds)
            if d < EPS:
                raise ValueError('%s(%s[%s]) invalid: %r' %
                                 (fidw.__name, 'ds', '', d))
            x = fdot(xs, *ds) / d
        elif b == 0:
            x = fmean(xs)
        else:
            raise ValueError('%s(%s=%r) invalid' % (fidw.__name, 'beta', beta))
    elif d < 0:
        i = ds.index(d)
        raise ValueError('%s(%s[%s]) invalid: %r' % (fidw.__name, 'ds', i, d))
    return x
예제 #10
0
def _pts2(points, closed, inull):
    '''(INTERNAL) Get the points to clip.
    '''
    if closed and inull:
        n, pts = len2(points)
        # only remove the final, closing point
        if n > 1 and _eq(pts[n - 1], pts[0]):
            n -= 1
            pts = pts[:n]
        if n < 2:
            raise PointsError(points=n, txt=_too_(_few_))
    else:
        n, pts = points2(points, closed=closed)
    return n, list(pts)
예제 #11
0
def _points2(points, closed, inull):
    '''(INTERNAL) Get the points to clip.
    '''
    if closed and inull:
        n, pts = len2(points)
        # only remove the final, closing point
        if n > 1 and _eq(pts[n - 1], pts[0]):
            n -= 1
            pts = pts[:n]
        if n < 3:
            raise PointsError('too few %s: %s' % ('points', n))
    else:
        n, pts = points2(points, closed=closed)
    return n, list(pts)
예제 #12
0
def fmean(xs):
    '''Compute the accurate mean M{sum(xs[i] for
       i=0..len(xs)) / len(xs)}.

       @arg xs: Values (C{scalar}s).

       @return: Mean value (C{float}).

       @raise OverflowError: Partial C{2sum} overflow.

       @raise ValueError: No B{C{xs}} values.
    '''
    n, xs = len2(xs)
    if n > 0:
        return fsum(xs) / n
    raise _ValueError(xs=xs)
예제 #13
0
 def __init__(self, corners, name):
     n, cs = 0, corners
     try:  # check the clip box/region
         n, cs = len2(cs)
         if n == 2:  # make a box
             b, l, t, r = boundsOf(cs, wrap=False)
             cs = LL_(b, l), LL_(t, l), LL_(t, r), LL_(b, r)
         n, cs = points2(cs, closed=True)
         self._cs = cs = cs[:n]
         self._nc = n
         self._cw = 1 if isclockwise(cs, adjust=False, wrap=False) else -1
         if self._cw != isconvex_(cs, adjust=False, wrap=False):
             raise ClipError
     except (ClipError, PointsError, TypeError, ValueError):
         raise ClipError(n, cs, name)
     self._name = name
예제 #14
0
def _h_x2(xs):
    '''(INTERNAL) Helper for L{hypot_} and L{hypot2_}.
    '''
    if xs:
        n, xs = len2(xs)
        if n > 0:
            h = float(max(abs(x) for x in xs))
            if h > 0:
                if n > 1:
                    X = Fsum(_1_0)
                    X.fadd((x / h)**2 for x in xs)
                    x2 = X.fsum_(-_1_0)
                else:
                    x2 = _1_0
            else:
                h = x2 = _0_0
            return h, x2
    raise _ValueError(xs=xs, txt=_too_(_few_))
예제 #15
0
 def __init__(self, corners, name=__name__):
     n, cs = 0, corners
     try:  # check the clip box/region
         n, cs = len2(cs)
         if n == 2:  # make a box
             b, l, t, r = boundsOf(cs, wrap=False)
             cs = LL_(b, l), LL_(t, l), LL_(t, r), LL_(b, r)
         n, cs = points2(cs, closed=True)
         self._cs = cs = cs[:n]
         self._nc = n
         self._cw = isconvex_(cs, adjust=False, wrap=False)
         if not self._cw:
             raise ValueError(_not_convex_)
         if areaOf(cs, adjust=True, radius=1, wrap=True) < EPS:
             raise ValueError('near-zero area')
     except (PointsError, TypeError, ValueError) as x:
         raise ClipError(name, n, cs, txt=str(x))
     self.name = name
예제 #16
0
def _allis2(llis, m=1, Error=HeightError):  # imported by .geoids
    # dtermine return type and convert lli C{LatLon}s to list
    if not isinstance(llis, tuple):  # llis are *args
        raise _AssertionError('type(%s): %r' % ('*llis', llis))

    n = len(llis)
    if n == 1:  # convert single lli to 1-item list
        llis = llis[0]
        try:
            n, llis = len2(llis)
            _as = _alist  # return list of interpolated heights
        except TypeError:  # single lli
            n, llis = 1, [llis]
            _as = _ascalar  # return single interpolated heights
    else:  # of 0, 2 or more llis
        _as = _atuple  # return tuple of interpolated heights

    if n < m:
        raise _insufficientError(m, Error=Error, llis=n)
    return _as, llis
예제 #17
0
def sumOf(vectors, Vector=Vector3d, **Vector_kwds):
    '''Compute the vectorial sum of several vectors.

       @arg vectors: Vectors to be added (L{Vector3d}[]).
       @kwarg Vector: Optional class for the vectorial sum (L{Vector3d}).
       @kwarg Vector_kwds: Optional B{C{Vector}} keyword arguments,
                           ignored if B{C{Vector=None}}.

       @return: Vectorial sum (B{C{Vector}}).

       @raise VectorError: No B{C{vectors}}.
    '''
    n, vectors = len2(vectors)
    if n < 1:
        raise VectorError('no vectors: %r' & (n, ))

    r = Vector3Tuple(fsum(v.x for v in vectors), fsum(v.y for v in vectors),
                     fsum(v.z for v in vectors))
    if Vector is not None:
        r = Vector(r.x, r.y, r.z, **Vector_kwds)  # PYCHOK x, y, z
    return r
예제 #18
0
def sumOf(vectors, Vector=Vector3d, **Vector_kwds):
    '''Compute the vectorial sum of several vectors.

       @arg vectors: Vectors to be added (L{Vector3d}[]).
       @kwarg Vector: Optional class for the vectorial sum (L{Vector3d}).
       @kwarg Vector_kwds: Optional B{C{Vector}} keyword arguments,
                           ignored if C{B{Vector}=None}.

       @return: Vectorial sum as B{C{Vector}} or if B{C{Vector}} is
                C{None}, a L{Vector3Tuple}C{(x, y, z)}.

       @raise VectorError: No B{C{vectors}}.
    '''
    n, vectors = len2(vectors)
    if n < 1:
        raise VectorError(vectors=n, txt=MISSING)

    v = Vector3Tuple(fsum(v.x for v in vectors),
                     fsum(v.y for v in vectors),
                     fsum(v.z for v in vectors))
    return _V_n(v, sumOf.__name__, Vector, Vector_kwds)
예제 #19
0
    def __init__(self, knots, beta=2, name=NN, **distanceTo_kwds):
        '''New L{HeightIDWdistanceTo} interpolator.

           @arg knots: The points with known height (C{LatLon}s).
           @kwarg beta: Inverse distance power (C{int} 1, 2, or 3).
           @kwarg name: Optional name for this height interpolator (C{str}).
           @kwarg distanceTo_kwds: Optional keyword arguments for the
                                   B{C{points}}' C{LatLon.distanceTo}
                                   method.

           @raise HeightError: Insufficient number of B{C{knots}} or
                               an invalid B{C{knot}} or B{C{beta}}.

           @raise ImportError: Package U{geographiclib
                  <https://PyPI.org/project/geographiclib>} missing
                  iff B{C{points}} are L{ellipsoidalKarney.LatLon}s.

           @note: All B{C{points}} I{must} be instances of the same
                  ellipsoidal or spherical C{LatLon} class, I{not
                  checked however}.
        '''
        n, self._ks = len2(knots)
        if n < self._kmin:
            raise _insufficientError(self._kmin, knots=n)
        for i, k in enumerate(self._ks):
            if not callable(getattr(k, _distanceTo_, None)):
                raise HeightError(_item_sq(_knots_, i), k, txt=_distanceTo_)

        # use knots[0] class and datum to create
        # compatible points in _HeightBase._height
        # instead of class LatLon_ and datum None
        self._datum = self._ks[0].datum
        self._LLis = self._ks[0].classof

        self.beta = beta
        if name:
            self.name = name
        if distanceTo_kwds:
            self._distanceTo_kwds = distanceTo_kwds
예제 #20
0
파일: utm.py 프로젝트: itzmejawad/PyGeodesy
    def __init__(self, AB, x, y):
        '''(INTERNAL) New Alpha or Beta Krüger series

           @arg AB: Krüger Alpha or Beta series coefficients
                      (C{4-, 6- or 8-tuple}).
           @arg x: Eta angle (C{radians}).
           @arg y: Ksi angle (C{radians}).
        '''
        n, j2 = len2(range(2, len(AB) * 2 + 1, 2))

        self._ab = AB
        self._pq = map2(mul, j2, self._ab)
#       assert len(self._ab) == len(self._pq) == n

        x2 = map2(mul, j2, (x,) * n)
        self._chx = map2(cosh, x2)
        self._shx = map2(sinh, x2)
#       assert len(x2) == len(self._chx) == len(self._shx) == n

        y2 = map2(mul, j2, (y,) * n)
        self._cy = map2(cos, y2)
        self._sy = map2(sin, y2)
예제 #21
0
def points2(points, closed=True, base=None, Error=PointsError):
    '''Check a path or polygon represented by points.

       @arg points: The path or polygon points (C{LatLon}[])
       @kwarg closed: Optionally, consider the polygon closed,
                      ignoring any duplicate or closing final
                      B{C{points}} (C{bool}).
       @kwarg base: Optionally, check all B{C{points}} against
                    this base class, if C{None} don't check.
       @kwarg Error: Exception to raise (C{ValueError}).

       @return: A L{Points2Tuple}C{(number, points)} with the number
                of points and the points C{list} or C{tuple}.

       @raise PointsError: Insufficient number of B{C{points}}.

       @raise TypeError: Some B{C{points}} are not B{C{base}}
                         compatible.
    '''
    n, points = len2(points)

    if closed:
        # remove duplicate or closing final points
        while n > 1 and points[n - 1] in (points[0], points[n - 2]):
            n -= 1
        # XXX following line is unneeded if points
        # are always indexed as ... i in range(n)
        points = points[:n]  # XXX numpy.array slice is a view!

    if n < (3 if closed else 1):
        raise Error('too few %s: %s' % ('points', n))

    if base and not (isNumpy2(points) or isTuple2(points)):
        for i in range(n):
            base.others(points[i], name='%s[%s]' % ('points', i))

    return Points2Tuple(n, points)