Example #1
0
def _streprs(prec, objs, fmt, ints, floats, strepr):
    '''(INTERNAL) Helper for C{fstr}, C{pairs}, C{reprs} and C{strs}
    '''
    if fmt in _EeFfGg:
        fGg = fmt in _Gg
        fmt = '%.' + str(abs(prec)) + fmt
    elif fmt.startswith('%'):
        fGg = False
        fmt = fmt.replace('*', str(abs(prec)))
    else:
        t = repr('[%s]%s' % ('%.*', '|'.join(_EeFfGg)))
        raise ValueError('%s not %s: %r' % ('fmt', t, fmt))

    for o in objs:
        if floats or isinstance(o, float):
            t = fmt % (float(o), )
            if ints and (isint(o, both=True) or  # for ...
                         # corner case testLcc lon0=-96.0
                         t.rstrip('0').endswith('.')):
                t = t.split('.')[0]
            elif prec > 1:
                t = fstrzs(t, ap1z=fGg)
        elif strepr:
            t = strepr(o)
        else:
            raise IsnotError('scalar', floats=o)
        yield t
Example #2
0
def fpowers(x, n, alts=0):
    '''Return a series of powers M{[x**i for i=1..n]}.

       @arg x: Value (C{scalar}).
       @arg n: Highest exponent (C{int}).
       @kwarg alts: Only alternating powers, starting with
                    this exponent (C{int}).

       @return: Powers of B{C{x}} (C{float}[]).

       @raise TypeError: Non-scalar B{C{x}} or B{C{n}} not C{int}.

       @raise ValueError: Non-finite B{C{x}} or non-positive B{C{n}}.
    '''
    if not isfinite(x):
        raise ValueError('not %s: %r' % ('finite', x))
    if not isint(n):
        raise IsnotError(int.__name_, n=n)
    elif n < 1:
        raise InvalidError(n=n)

    xs = [x]
    for _ in range(1, n):
        xs.append(xs[-1] * x)

    if alts > 0:  # x**2, x**4, ...
        # XXX PyChecker chokes on xs[alts-1::2]
        xs = xs[slice(alts - 1, None, 2)]

    # XXX PyChecker claims result is None
    return xs
Example #3
0
def pairs(items, prec=6, fmt='F', ints=False, sep='='):
    '''Convert items to I{name=value} strings, with C{float}s handled like L{fstr}.

       @arg items: Name-value pairs (C{dict} or 2-{tuple}s of any C{type}s).
       @kwarg prec: The C{float} precision, number of decimal digits (0..9).
                    Trailing zero decimals are stripped if B{C{prec}} is
                    positive, but kept for negative B{C{prec}} values.
       @kwarg fmt: Optional, float format (C{str}).
       @kwarg ints: Optionally, remove the decimal dot (C{bool}).
       @kwarg sep: Separator joining I{names} and I{values} (C{str}).

       @return: A C{tuple(sep.join(t) for t in zip(names, reprs(values,...)))}
                of C{str}s.
    '''
    try:
        if isinstance(items, dict):
            items = sorted(items.items())
        elif not isinstance(items, (list, tuple)):
            items = tuple(items)
        # can't unzip empty items tuple, list, etc.
        n, v = zip(*items) if items else ((), ())
    except (TypeError, ValueError):
        raise IsnotError('dict', '2-tuples', items=items)
    v = _streprs(prec, v, fmt, ints, False, repr)
    return tuple(sep.join(t) for t in zip(map(str, n), v))
Example #4
0
    def latlon2(self, datum=None):
        '''Convert this WM coordinate to a lat- and longitude.

           @kwarg datum: Optional ellipsoidal datum (C{Datum}).

           @return: A L{LatLon2Tuple}C{(lat, lon)}.

           @raise TypeError: Non-ellipsoidal B{C{datum}}.

           @see: Method C{toLatLon}.
        '''
        r = self.radius
        x = self._x / r
        y = 2 * atan(exp(self._y / r)) - PI_2
        if datum:
            _xinstanceof(Datum, datum=datum)
            E = datum.ellipsoid
            if not E.isEllipsoidal:
                raise IsnotError('ellipsoidal', datum=datum)
            # <https://Earth-Info.NGA.mil/GandG/wgs84/web_mercator/
            #        %28U%29%20NGA_SIG_0011_1.0.0_WEBMERC.pdf>
            y = y / r
            if E.e:
                y -= E.e * atanh(E.e * tanh(y))  # == E.es_atanh(tanh(y))
            y *= E.a
            x *= E.a / r

        r = LatLon2Tuple(degrees90(y), degrees180(x))
        return self._xnamed(r)
Example #5
0
    def datum(self, datum):
        '''Set this cartesian's C{datum} I{without conversion}.

           @arg datum: New datum (L{Datum}).

           @raise TypeError: The B{C{datum}} is not a L{Datum}.
        '''
        _xinstanceof(Datum, datum=datum)
        d = self.datum
        if d is not None:
            if d.isEllipsoidal and not datum.isEllipsoidal:
                raise IsnotError('ellipsoidal', datum=datum)
            elif d.isSpherical and not datum.isSpherical:
                raise IsnotError('spherical', datum=datum)
        self._update(datum != d)
        self._datum = datum
Example #6
0
def hausdorff_(model,
               target,
               both=False,
               early=True,
               seed=None,
               units='',
               distance=None,
               point=_point):
    '''Compute the C{directed} or C{symmetric} U{Hausdorff distance<https://
       WikiPedia.org/wiki/Hausdorff_distance>} between 2 sets of points with or
       without U{early breaking<https://Publik.TUWien.ac.AT/files/PubDat_247739.pdf>}
       and U{random sampling<https://Publik.TUWien.ac.AT/files/PubDat_247739.pdf>}.

       @arg model: First set of points (C{LatLon}[], C{Numpy2LatLon}[],
                   C{Tuple2LatLon}[] or C{other}[]).
       @arg target: Second set of points (C{LatLon}[], C{Numpy2LatLon}[],
                    C{Tuple2LatLon}[] or C{other}[]).
       @kwarg both: Return the C{directed} (forward only) or the C{symmetric}
                    (combined forward and reverse) C{Hausdorff} distance (C{bool}).
       @kwarg early: Enable or disable U{early breaking<https://Publik.TUWien.ac.AT/
                     files/PubDat_247739.pdf>} (C{bool}).
       @kwarg seed: Random sampling seed (C{any}) or C{None}, C{0} or C{False} for no
                    U{random sampling<https://Publik.TUWien.ac.AT/files/PubDat_247739.pdf>}.
       @kwarg units: Optional, name of the distance units (C{str}).
       @kwarg distance: Callable returning the distance between a B{C{model}}
                        and B{C{target}} point (signature C{(point1, point2)}).
       @kwarg point: Callable returning the B{C{model}} or B{C{target}} point
                     suitable for B{C{distance}} (signature C{(point)}).

       @return: A L{Hausdorff6Tuple}C{(hd, i, j, mn, md, units)}.

       @raise HausdorffError: Insufficient number of B{C{model}} or B{C{target}} points.

       @raise TypeError: If B{C{distance}} or B{C{point}} is not callable.
    '''
    if not callable(distance):
        raise IsnotError(callable.__name__, distance=distance)
    if not callable(point):
        raise IsnotError(callable.__name__, point=point)

    _, ps1 = points2(model, closed=False, Error=HausdorffError)
    _, ps2 = points2(target, closed=False, Error=HausdorffError)
    return _hausdorff_(ps1, ps2, both, early, seed, units, distance, point)
Example #7
0
    def __new__(cls, cll, precision=3, name=''):
        '''New L{Georef} from an other L{Georef} instance or georef
           C{str} or from a C{LatLon} instance or lat-/longitude C{str}.

           @arg cll: Cell or location (L{Georef} or C{str}, C{LatLon}
                     or C{str}).
           @kwarg precision: Optional, the desired georef resolution
                             and length (C{int} 0..11), see function
                             L{wgrs.encode} for more details.
           @kwarg name: Optional name (C{str}).

           @return: New L{Georef}.

           @raise RangeError: Invalid B{C{cll}} lat- or longitude.

           @raise TypeError: Invalid B{C{cll}}.

           @raise WGRSError: INValid or non-alphanumeric B{C{cll}}.
        '''
        h = None

        if isinstance(cll, Georef):
            g, p = _2geostr2(str(cll))
            self = str.__new__(cls, g)
            self._latlon = LatLon2Tuple(*cll._latlon)
            self._name = cll._name
            self._precision = p  # cll._precision

        elif isstr(cll):
            if ',' in cll:
                lat, lon, h = _2fllh(*parse3llh(cll, height=None))
                g = encode(lat, lon, precision=precision, height=h)  # PYCHOK false
                self = str.__new__(cls, g)
                self._latlon = LatLon2Tuple(lat, lon)
                self._precision = Precision_(precision, high=_MaxPrec)
            else:
                self = str.__new__(cls, cll.upper())
                self._decode()

        else:  # assume LatLon
            try:
                lat, lon, h = _2fllh(cll.lat, cll.lon)
                h = getattr(cll, 'height', h)
            except AttributeError:
                raise IsnotError('valid', **{Georef.__name__: cll})
            g = encode(lat, lon, precision=precision, height=h)  # PYCHOK false
            self = str.__new__(cls, g)
            self._latlon = LatLon2Tuple(lat, lon)
            self._precision = Precision_(precision, high=_MaxPrec)

        if h not in (None, _MISSING):
            self._height = Height(h)
        if name:
            self.name = name
        return self
Example #8
0
def _2Geohash(geohash):
    '''(INTERNAL) Check or create a Geohash instance.
    '''
    if not isinstance(geohash, Geohash):
        try:
            geohash = Geohash(geohash)
        except (TypeError, ValueError):
            raise IsnotError(Geohash.__name__,
                             str.__name__,
                             'LatLon',
                             geohash=geohash)
    return geohash
Example #9
0
    def times(self, factor):
        '''Multiply this vector by a scalar.

           @arg factor: Scale factor (C{scalar}).

           @return: New, scaled vector (L{Vector3d}).

           @raise TypeError: Non-scalar B{C{factor}}.
        '''
        if not isscalar(factor):
            raise IsnotError('scalar', factor=factor)
        return self.classof(self.x * factor, self.y * factor, self.z * factor)
Example #10
0
    def to4Tuple(self, datum):
        '''Extend this L{PhiLam3Tuple} to a L{PhiLam4Tuple}.

           @arg datum: The datum to add (C{Datum}).

           @return: A L{PhiLam4Tuple}C{(phi, lam, height, datum)}.

           @raise TypeError: If B{C{datum}} not a C{Datum}.
        '''
        from pygeodesy.datum import Datum
        if not isinstance(datum, Datum):
            raise IsnotError(Datum.__name__, datum=datum)
        return self._xtend(PhiLam4Tuple, datum)
Example #11
0
    def datum(self, datum):
        '''Set this point's datum I{without conversion}.

           @arg datum: New datum (L{Datum}).

           @raise TypeError: The B{C{datum}} is not a L{Datum}
                             or not ellipsoidal.
        '''
        _xinstanceof(Datum, datum=datum)
        if not datum.isEllipsoidal:
            raise IsnotError('ellipsoidal', datum=datum)
        self._update(datum != self._datum)
        self._datum = datum
Example #12
0
    def _xrenamed(self, inst):
        '''(INTERNAL) Rename the instance' C{.name = self.name}.

           @arg inst: The instance (C{_Named}).

           @return: The B{C{inst}}, named if not named before.
        '''
        if not isinstance(inst, _Named):
            raise IsnotError('valid', inst=inst)

        if inst.name != self.name:
            inst.name = self.name
        return inst
Example #13
0
    def toDatum(self, datum):
        '''Convert this conic to the given datum.

           @arg datum: Ellipsoidal datum to use (L{Datum}).

           @return: Converted conic, unregistered (L{Conic}).

           @raise TypeError: Non-ellipsoidal B{C{datum}}.
        '''
        E = datum.ellipsoid
        if not E.isEllipsoidal:
            raise IsnotError('ellipsoidal', datum=datum)

        c = self
        if c._e != E.e or c._datum != datum:

            c = Conic(None, 0, name=self._name)
            self._dup2(c)
            c._datum = datum
            c._e = E.e

            if abs(c._par1 - c._par2) < EPS:
                m1 = c._mdef(c._phi0)
                t1 = c._tdef(c._phi0)
                t0 = t1
                k = 1
                n = sin(c._phi0)
                sp = 1
            else:
                m1 = c._mdef(c._par1)
                m2 = c._mdef(c._par2)
                t1 = c._tdef(c._par1)
                t2 = c._tdef(c._par2)
                t0 = c._tdef(c._phi0)
                k = c._k0
                n  = (log(m1) - log(m2)) \
                   / (log(t1) - log(t2))
                sp = 2

            F = m1 / (n * pow(t1, n))

            c._aF = k * E.a * F
            c._n = n
            c._n_ = 1 / n
            c._r0 = c._rdef(t0)
            c._SP = sp

        return c
Example #14
0
def frange(start, number, step=1):
    '''Generate a range of C{float}s.

       @arg start: First value (C{float}).
       @arg number: The number of C{float}s to generate (C{int}).
       @kwarg step: Increment value (C{float}).

       @return: A generator (C{float}s).

       @see: U{NumPy.prod<https://docs.SciPy.org/doc/
             numpy/reference/generated/numpy.arange.html>}.
    '''
    if not isint(number):
        raise IsnotError(int.__name_, number=number)
    for i in range(number):
        yield start + i * step
Example #15
0
    def dividedBy(self, factor):
        '''Divide this vector by a scalar.

           @arg factor: The divisor (C{scalar}).

           @return: New, scaled vector (L{Vector3d}).

           @raise TypeError: Non-scalar B{C{factor}}.

           @raise VectorError: Invalid or zero B{C{factor}}.
        '''
        if not isscalar(factor):
            raise IsnotError('scalar', factor=factor)
        try:
            return self.times(1.0 / factor)
        except (ValueError, ZeroDivisionError):
            raise InvalidError(factor=factor, Error=VectorError)
Example #16
0
def frechet_(points1, points2, distance=None, units=''):
    '''Compute the I{discrete} U{Fréchet<https://WikiPedia.org/wiki/Frechet_distance>}
       distance between two paths given as sets of points.

       @arg points1: First set of points (C{LatLon}[], L{Numpy2LatLon}[],
                     L{Tuple2LatLon}[] or C{other}[]).
       @arg points2: Second set of points (C{LatLon}[], L{Numpy2LatLon}[],
                     L{Tuple2LatLon}[] or C{other}[]).
       @kwarg distance: Callable returning the distance between a B{C{points1}}
                        and a B{C{points2}} point (signature C{(point1, point2)}).
       @kwarg units: Optional, name of the distance units (C{str}).

       @return: A L{Frechet6Tuple}C{(fd, fi1, fi2, r, n, units)} where C{fi1}
                and C{fi2} are type C{int} indices into B{C{points1}} respectively
                B{C{points2}}.

       @raise FrechetError: Insufficient number of B{C{points1}} or B{C{points2}}.

       @raise RecursionError: Recursion depth exceeded, see U{sys.getrecursionlimit()
                              <https://docs.Python.org/3/library/sys.html#sys.getrecursionlimit>}.

       @raise TypeError: If B{C{distance}} is not a callable.

       @note: Function L{frechet_} does not support I{fractional} indices for
              intermediate B{C{points1}} and B{C{points2}}.
    '''
    if not callable(distance):
        raise IsnotError(callable.__name__, distance=distance)

    n1, ps1 = _points2(points1, closed=False, Error=FrechetError)
    n2, ps2 = _points2(points2, closed=False, Error=FrechetError)

    def dF(i1, i2):
        return distance(ps1[i1], ps2[i2])

    return _frechet_(n1, 1, n2, 1, dF, units)
Example #17
0
def _2epoch(epoch):  # imported by .ellipsoidalBase.py
    '''(INTERNAL) Validate an C{epoch}.
    '''
    if isscalar(epoch) and epoch > 0:  # XXX 1970?
        return _F(epoch)
    raise IsnotError('scalar', epoch=epoch)