pygeodesy 24.8.4__py2.py3-none-any.whl → 24.9.9__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.9.9.dist-info}/METADATA +17 -16
- PyGeodesy-24.9.9.dist-info/RECORD +118 -0
- {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.9.9.dist-info}/WHEEL +1 -1
- pygeodesy/__init__.py +23 -23
- pygeodesy/__main__.py +46 -47
- pygeodesy/auxilats/_CX_4.py +104 -181
- pygeodesy/auxilats/_CX_6.py +152 -277
- pygeodesy/auxilats/_CX_8.py +211 -438
- pygeodesy/auxilats/_CX_Rs.py +222 -0
- pygeodesy/auxilats/__init__.py +2 -2
- pygeodesy/auxilats/__main__.py +30 -38
- pygeodesy/auxilats/auxDST.py +2 -2
- pygeodesy/auxilats/auxLat.py +28 -36
- pygeodesy/auxilats/auxily.py +30 -50
- pygeodesy/basics.py +18 -7
- pygeodesy/booleans.py +10 -11
- pygeodesy/cartesianBase.py +5 -5
- pygeodesy/constants.py +35 -34
- pygeodesy/ellipsoidalBase.py +18 -15
- pygeodesy/ellipsoidalExact.py +2 -2
- pygeodesy/ellipsoidalGeodSolve.py +2 -2
- pygeodesy/ellipsoidalKarney.py +2 -2
- pygeodesy/ellipsoidalNvector.py +2 -2
- pygeodesy/ellipsoidalVincenty.py +7 -6
- pygeodesy/elliptic.py +154 -88
- pygeodesy/epsg.py +3 -3
- pygeodesy/etm.py +71 -59
- pygeodesy/fmath.py +99 -90
- pygeodesy/fsums.py +201 -14
- pygeodesy/gars.py +9 -8
- pygeodesy/geodesici.py +6 -5
- pygeodesy/geodesicx/_C4_24.py +1 -3
- pygeodesy/geodesicx/_C4_27.py +1 -3
- pygeodesy/geodesicx/_C4_30.py +1 -3
- pygeodesy/geodesicx/__init__.py +1 -1
- pygeodesy/geodesicx/__main__.py +44 -46
- pygeodesy/geodesicx/gx.py +3 -3
- pygeodesy/geodesicx/gxarea.py +5 -5
- pygeodesy/geodesicx/gxbases.py +32 -18
- pygeodesy/geodsolve.py +3 -3
- pygeodesy/geohash.py +18 -11
- pygeodesy/geoids.py +293 -315
- pygeodesy/heights.py +150 -158
- pygeodesy/internals.py +70 -9
- pygeodesy/interns.py +4 -4
- pygeodesy/karney.py +83 -60
- pygeodesy/ktm.py +4 -4
- pygeodesy/latlonBase.py +13 -7
- pygeodesy/lazily.py +13 -8
- pygeodesy/ltp.py +5 -6
- pygeodesy/ltpTuples.py +7 -1
- pygeodesy/mgrs.py +47 -42
- pygeodesy/named.py +8 -4
- pygeodesy/namedTuples.py +14 -1
- pygeodesy/osgr.py +7 -7
- pygeodesy/points.py +2 -2
- pygeodesy/props.py +7 -6
- pygeodesy/resections.py +7 -7
- pygeodesy/rhumb/__init__.py +1 -1
- pygeodesy/rhumb/aux_.py +42 -60
- pygeodesy/rhumb/solve.py +3 -3
- pygeodesy/simplify.py +10 -10
- pygeodesy/sphericalBase.py +3 -3
- pygeodesy/sphericalTrigonometry.py +2 -2
- pygeodesy/streprs.py +3 -3
- pygeodesy/triaxials.py +207 -201
- pygeodesy/units.py +3 -3
- pygeodesy/unitsBase.py +4 -4
- pygeodesy/utmupsBase.py +3 -3
- pygeodesy/vector2d.py +158 -51
- pygeodesy/vector3d.py +13 -52
- pygeodesy/vector3dBase.py +81 -63
- pygeodesy/webmercator.py +3 -3
- pygeodesy/wgrs.py +20 -22
- PyGeodesy-24.8.4.dist-info/RECORD +0 -117
- {PyGeodesy-24.8.4.dist-info → PyGeodesy-24.9.9.dist-info}/top_level.txt +0 -0
pygeodesy/heights.py
CHANGED
|
@@ -78,8 +78,8 @@ from pygeodesy.errors import _AssertionError, LenError, PointsError, \
|
|
|
78
78
|
# cosineLaw, equirectangular4, euclidean, flatLocal, \
|
|
79
79
|
# flatPolar, haversine, thomas, vincentys # _MODS.into
|
|
80
80
|
# from pygeodesy.internals import _version2 # _MODS
|
|
81
|
-
from pygeodesy.interns import NN, _COMMASPACE_,
|
|
82
|
-
|
|
81
|
+
from pygeodesy.interns import NN, _COMMASPACE_, _insufficient_, _NOTEQUAL_, \
|
|
82
|
+
_PLUS_, _scipy_, _SPACE_, _STAR_
|
|
83
83
|
from pygeodesy.lazily import _ALL_DOCS, _ALL_LAZY, _ALL_MODS as _MODS, _FOR_DOCS
|
|
84
84
|
from pygeodesy.named import _name2__, _Named
|
|
85
85
|
from pygeodesy.points import _distanceTo, LatLon_, Fmt, radians, _Wrap
|
|
@@ -91,12 +91,12 @@ from pygeodesy.units import _isDegrees, Float_, Int_
|
|
|
91
91
|
# from math import radians # from .points
|
|
92
92
|
|
|
93
93
|
__all__ = _ALL_LAZY.heights
|
|
94
|
-
__version__ = '24.
|
|
94
|
+
__version__ = '24.08.24'
|
|
95
95
|
|
|
96
|
-
_error_
|
|
97
|
-
_formy
|
|
98
|
-
|
|
99
|
-
|
|
96
|
+
_error_ = 'error'
|
|
97
|
+
_formy = _MODS.into(formy=__name__)
|
|
98
|
+
_linear_ = 'linear'
|
|
99
|
+
_llis_ = 'llis'
|
|
100
100
|
|
|
101
101
|
|
|
102
102
|
class HeightError(PointsError):
|
|
@@ -144,26 +144,11 @@ def _as_llis2(llis, m=1, Error=HeightError): # in .geoids
|
|
|
144
144
|
_as = _atuple # return tuple of interpolated heights
|
|
145
145
|
|
|
146
146
|
if n < m:
|
|
147
|
-
raise
|
|
147
|
+
raise _InsufficientError(m, Error=Error, llis=n)
|
|
148
148
|
return _as, llis
|
|
149
149
|
|
|
150
150
|
|
|
151
|
-
def
|
|
152
|
-
LLis, d = inst._LLis, inst.datum
|
|
153
|
-
if _isDegrees(lats) and _isDegrees(lons):
|
|
154
|
-
llis = LLis(lats, lons, datum=d)
|
|
155
|
-
else:
|
|
156
|
-
n, lats = len2(lats)
|
|
157
|
-
m, lons = len2(lons)
|
|
158
|
-
if n != m:
|
|
159
|
-
# format a LenError, but raise an Error
|
|
160
|
-
e = LenError(inst.__class__, lats=n, lons=m, txt=None)
|
|
161
|
-
raise e if Error is LenError else Error(str(e))
|
|
162
|
-
llis = [LLis(*t, datum=d) for t in zip(lats, lons)]
|
|
163
|
-
return inst(llis, **wrap) # __call__(lli) or __call__(llis)
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
def _insufficientError(need, Error=HeightError, **name_value): # PYCHOK no cover
|
|
151
|
+
def _InsufficientError(need, Error=HeightError, **name_value): # PYCHOK no cover
|
|
167
152
|
# create an insufficient Error instance
|
|
168
153
|
t = _COMMASPACE_(_insufficient_, str(need) + _PLUS_)
|
|
169
154
|
return Error(txt=t, **name_value)
|
|
@@ -171,39 +156,48 @@ def _insufficientError(need, Error=HeightError, **name_value): # PYCHOK no cove
|
|
|
171
156
|
|
|
172
157
|
def _orderedup(ts, lo=EPS, hi=PI2-EPS):
|
|
173
158
|
# clip, order and remove duplicates
|
|
174
|
-
# p = 0
|
|
175
|
-
# for k in sorted(max(lo, min(hi, t)) for t in ts):
|
|
176
|
-
# if k > p:
|
|
177
|
-
# yield k
|
|
178
|
-
# p = k
|
|
179
159
|
return sorted(set(max(lo, min(hi, t)) for t in ts)) # list
|
|
180
160
|
|
|
181
161
|
|
|
182
|
-
def _xyhs(wrap=False, **name_lls):
|
|
162
|
+
def _xyhs(wrap=False, _lat=_90_0, _lon=_180_0, **name_lls):
|
|
183
163
|
# map (lat, lon, h) to (x, y, h) in radians, offset
|
|
184
164
|
# x as 0 <= lon <= PI2 and y as 0 <= lat <= PI
|
|
185
165
|
name, lls = _xkwds_item2(name_lls)
|
|
186
|
-
|
|
187
|
-
_m, _r, _w = max, radians, _Wrap._latlonop(wrap)
|
|
166
|
+
_r, _w = radians, _Wrap._latlonop(wrap)
|
|
188
167
|
try:
|
|
189
168
|
for i, ll in enumerate(lls):
|
|
190
169
|
y, x = _w(ll.lat, ll.lon)
|
|
191
|
-
yield
|
|
192
|
-
|
|
170
|
+
yield max(_0_0, _r(x + _lon)), \
|
|
171
|
+
max(_0_0, _r(y + _lat)), ll.height
|
|
193
172
|
except Exception as e:
|
|
194
173
|
i = Fmt.INDEX(name, i)
|
|
195
174
|
raise HeightError(i, ll, cause=e)
|
|
196
175
|
|
|
197
176
|
|
|
198
|
-
class
|
|
177
|
+
class _HeightNamed(_Named): # in .geoids
|
|
199
178
|
'''(INTERNAL) Interpolator base class.
|
|
200
179
|
'''
|
|
201
180
|
_datum = _WGS84 # default
|
|
181
|
+
_Error = HeightError
|
|
202
182
|
_kmin = 2 # min number of knots
|
|
183
|
+
|
|
203
184
|
_LLis = LatLon_ # ._height class
|
|
204
185
|
_np_sp = None # (numpy, scipy)
|
|
205
186
|
_wrap = None # wrap knots and llis
|
|
206
187
|
|
|
188
|
+
def _as_lls(self, lats, lons): # in .geoids
|
|
189
|
+
LLis, d = self._LLis, self.datum
|
|
190
|
+
if _isDegrees(lats) and _isDegrees(lons):
|
|
191
|
+
llis = LLis(lats, lons, datum=d)
|
|
192
|
+
else:
|
|
193
|
+
n, lats = len2(lats)
|
|
194
|
+
m, lons = len2(lons)
|
|
195
|
+
if n != m: # format a LenError, but raise self._Error
|
|
196
|
+
e = LenError(self.__class__, lats=n, lons=m, txt=None)
|
|
197
|
+
raise self._Error(str(e))
|
|
198
|
+
llis = [LLis(*t, datum=d) for t in zip(lats, lons)]
|
|
199
|
+
return llis
|
|
200
|
+
|
|
207
201
|
@property_RO
|
|
208
202
|
def datum(self):
|
|
209
203
|
'''Get the C{datum} setting or the default (L{Datum}).
|
|
@@ -223,9 +217,14 @@ class _HeightBase(_Named): # in .geoids
|
|
|
223
217
|
return self._wrap
|
|
224
218
|
|
|
225
219
|
|
|
226
|
-
class
|
|
220
|
+
class _HeightBase(_HeightNamed): # in .geoids
|
|
227
221
|
'''(INTERNAL) Interpolator base class.
|
|
228
222
|
'''
|
|
223
|
+
_k2interp2d = {-1: _linear_, # in .geoids._GeoidBase.__init__
|
|
224
|
+
-2: _linear_, # for backward compatibility
|
|
225
|
+
-3: 'cubic',
|
|
226
|
+
-5: 'quintic'}
|
|
227
|
+
|
|
229
228
|
def __call__(self, *llis, **wrap): # PYCHOK no cover
|
|
230
229
|
'''Interpolate the height for one or several locations. I{Must be overloaded}.
|
|
231
230
|
|
|
@@ -259,12 +258,29 @@ class _HeightsBase(_HeightBase): # in .geoids
|
|
|
259
258
|
'''(INTERNAL) I{Must be overloaded}.'''
|
|
260
259
|
self._notOverloaded(*args)
|
|
261
260
|
|
|
262
|
-
def
|
|
261
|
+
def _evalls(self, llis, **wrap): # XXX single arg, not *args
|
|
263
262
|
_as, xis, yis, _ = self._as_xyllis4(llis, **wrap)
|
|
264
263
|
try: # SciPy .ev signature: y first, then x!
|
|
265
264
|
return _as(self._ev(yis, xis))
|
|
266
265
|
except Exception as x:
|
|
267
|
-
raise _SciPyIssue(x)
|
|
266
|
+
raise _SciPyIssue(x, self._ev_name)
|
|
267
|
+
|
|
268
|
+
def _ev2d(self, x, y): # PYCHOK no cover
|
|
269
|
+
'''(INTERNAL) I{Must be overloaded}.'''
|
|
270
|
+
self._notOverloaded(x, y)
|
|
271
|
+
|
|
272
|
+
@property_RO
|
|
273
|
+
def _ev_name(self):
|
|
274
|
+
'''(INTERNAL) Get the name of the C{.ev} method.
|
|
275
|
+
'''
|
|
276
|
+
_ev = str(self._ev)
|
|
277
|
+
if _scipy_ not in _ev:
|
|
278
|
+
_ev = str(self._ev2d)
|
|
279
|
+
# '<scipy.interpolate._interpolate.interp2d object at ...>
|
|
280
|
+
# '<function _HeightBase._interp2d.<locals>._bisplev at ...>
|
|
281
|
+
# '<bound method BivariateSpline.ev of ... object at ...>
|
|
282
|
+
_ev = _ev[1:].split(None, 4)
|
|
283
|
+
return Fmt.PAREN(_ev['sfb'.index(_ev[0][0])])
|
|
268
284
|
|
|
269
285
|
def height(self, lats, lons, **wrap): # PYCHOK no cover
|
|
270
286
|
'''Interpolate the height for one or several lat-/longitudes. I{Must be overloaded}.
|
|
@@ -285,7 +301,35 @@ class _HeightsBase(_HeightBase): # in .geoids
|
|
|
285
301
|
|
|
286
302
|
@raise SciPyWarning: A C{scipy} warning as exception.
|
|
287
303
|
'''
|
|
288
|
-
self.
|
|
304
|
+
lls = self._as_lls(lats, lons)
|
|
305
|
+
return self(lls, **wrap) # __call__(ll) or __call__(lls)
|
|
306
|
+
|
|
307
|
+
def _interp2d(self, xs, ys, hs, kind=-3):
|
|
308
|
+
'''Create a C{scipy.interpolate.interp2d} or C{-.bisplrep/-ev}
|
|
309
|
+
interpolator before, respectively since C{SciPy} version 1.14.
|
|
310
|
+
'''
|
|
311
|
+
try:
|
|
312
|
+
spi = self.scipy_interpolate
|
|
313
|
+
if self._scipy_version() < (1, 14) and kind in self._k2interp2d:
|
|
314
|
+
# SciPy.interpolate.interp2d kind 'linear', 'cubic' or 'quintic'
|
|
315
|
+
# DEPRECATED since scipy 1.10, removed altogether in 1.14
|
|
316
|
+
self._ev2d = spi.interp2d(xs, ys, hs, kind=self._k2interp2d[kind])
|
|
317
|
+
|
|
318
|
+
else: # <https://scipy.GitHub.io/devdocs/tutorial/interpolate/interp_transition_guide.html>
|
|
319
|
+
k = self._kxky(abs(kind))
|
|
320
|
+
# spi.RectBivariateSpline needs strictly ordered xs and ys
|
|
321
|
+
r = spi.bisplrep(xs, ys, hs.T, kx=k, ky=k)
|
|
322
|
+
|
|
323
|
+
def _bisplev(x, y):
|
|
324
|
+
return spi.bisplev(x, y, r) # .T
|
|
325
|
+
|
|
326
|
+
self._ev2d = _bisplev
|
|
327
|
+
|
|
328
|
+
except Exception as x:
|
|
329
|
+
raise _SciPyIssue(x, self._ev_name)
|
|
330
|
+
|
|
331
|
+
def _kxky(self, kind):
|
|
332
|
+
return Int_(kind=kind, low=1, high=5, Error=self._Error)
|
|
289
333
|
|
|
290
334
|
def _np_sp2(self, throwarnings=False): # PYCHOK no cover
|
|
291
335
|
'''(INTERNAL) Import C{numpy} and C{scipy}, once.
|
|
@@ -329,85 +373,60 @@ class _HeightsBase(_HeightBase): # in .geoids
|
|
|
329
373
|
xs, ys, hs = zip(*_xyhs(knots=knots, wrap=wrap)) # PYCHOK yield
|
|
330
374
|
n = len(hs)
|
|
331
375
|
if n < self.kmin:
|
|
332
|
-
raise
|
|
376
|
+
raise _InsufficientError(self.kmin, knots=n)
|
|
333
377
|
if name:
|
|
334
378
|
self.name = name
|
|
335
379
|
return map1(self.numpy.array, xs, ys, hs)
|
|
336
380
|
|
|
337
381
|
|
|
338
|
-
class HeightCubic(
|
|
382
|
+
class HeightCubic(_HeightBase):
|
|
339
383
|
'''Height interpolator based on C{SciPy} U{interp2d<https://docs.SciPy.org/
|
|
340
384
|
doc/scipy/reference/generated/scipy.interpolate.interp2d.html>}
|
|
341
|
-
C{kind='cubic'}.
|
|
385
|
+
C{kind='cubic'} or U{bisplrep/-ev<https://docs.SciPy.org/doc/scipy/
|
|
386
|
+
reference/generated/scipy.interpolate.interp2d.html>} C{kx=ky=3}.
|
|
342
387
|
'''
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
_kmin = 16
|
|
388
|
+
_kind = -3
|
|
389
|
+
_kmin = 16
|
|
346
390
|
|
|
347
391
|
def __init__(self, knots, **name_wrap):
|
|
348
392
|
'''New L{HeightCubic} interpolator.
|
|
349
393
|
|
|
350
394
|
@arg knots: The points with known height (C{LatLon}s).
|
|
351
|
-
@kwarg name_wrap: Optional C{B{name}=NN} for this height interpolator
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
C{True} (C{bool}).
|
|
395
|
+
@kwarg name_wrap: Optional C{B{name}=NN} for this height interpolator (C{str})
|
|
396
|
+
and keyword argument C{b{wrap}=False} to wrap or I{normalize} all
|
|
397
|
+
B{C{knots}} and B{C{llis}} locations iff C{True} (C{bool}).
|
|
355
398
|
|
|
356
|
-
@raise HeightError: Insufficient number of B{C{knots}} or
|
|
357
|
-
invalid B{C{knot}}.
|
|
399
|
+
@raise HeightError: Insufficient number of B{C{knots}} or invalid B{C{knot}}.
|
|
358
400
|
|
|
359
|
-
@raise ImportError: Package C{numpy} or C{scipy} not found
|
|
360
|
-
or not installed.
|
|
401
|
+
@raise ImportError: Package C{numpy} or C{scipy} not found or not installed.
|
|
361
402
|
|
|
362
|
-
@raise SciPyError: A C{scipy
|
|
403
|
+
@raise SciPyError: A C{scipy} issue.
|
|
363
404
|
|
|
364
|
-
@raise SciPyWarning: A C{scipy
|
|
365
|
-
as exception.
|
|
405
|
+
@raise SciPyWarning: A C{scipy} warning as exception.
|
|
366
406
|
'''
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
xs, ys, hs = self._xyhs3(knots, **name_wrap)
|
|
370
|
-
try: # SciPy.interpolate.interp2d kind 'linear' or 'cubic'
|
|
371
|
-
self._interp2d = spi.interp2d(xs, ys, hs, kind=self._kind)
|
|
372
|
-
except Exception as x:
|
|
373
|
-
raise _SciPyIssue(x)
|
|
407
|
+
xs_yx_hs = self._xyhs3(knots, **name_wrap)
|
|
408
|
+
self._interp2d(*xs_yx_hs, kind=self._kind)
|
|
374
409
|
|
|
375
410
|
def __call__(self, *llis, **wrap):
|
|
376
411
|
'''Interpolate the height for one or several locations.
|
|
377
412
|
|
|
378
|
-
@
|
|
379
|
-
|
|
380
|
-
@raise SciPyWarning: A C{scipy.interpolate.interp2d} warning
|
|
381
|
-
as exception.
|
|
382
|
-
|
|
383
|
-
@see: L{Here<_HeightsBase.__call__>} for further details.
|
|
413
|
+
@see: L{Here<_HeightBase.__call__>} for further details.
|
|
384
414
|
'''
|
|
385
|
-
return
|
|
415
|
+
return self._evalls(llis, **wrap)
|
|
386
416
|
|
|
387
|
-
def _ev(self, yis, xis): # PYCHOK
|
|
388
|
-
# to make SciPy .interp2d
|
|
417
|
+
def _ev(self, yis, xis): # PYCHOK overwritten with .RectBivariateSpline.ev
|
|
418
|
+
# to make SciPy .interp2d single (x, y) signature
|
|
389
419
|
# match SciPy .ev signature(ys, xs), flipped multiples
|
|
390
|
-
return map(self.
|
|
391
|
-
|
|
392
|
-
def height(self, lats, lons, **wrap):
|
|
393
|
-
'''Interpolate the height for one or several lat-/longitudes.
|
|
394
|
-
|
|
395
|
-
@raise SciPyError: A C{scipy.interpolate.interp2d} issue.
|
|
396
|
-
|
|
397
|
-
@raise SciPyWarning: A C{scipy.interpolate.interp2d} warning
|
|
398
|
-
as exception.
|
|
399
|
-
|
|
400
|
-
@see: L{Here<_HeightsBase.height>} for further details.
|
|
401
|
-
'''
|
|
402
|
-
return _height_called(self, lats, lons, **wrap)
|
|
420
|
+
return map(self._ev2d, xis, yis)
|
|
403
421
|
|
|
404
422
|
|
|
405
423
|
class HeightLinear(HeightCubic):
|
|
406
424
|
'''Height interpolator based on C{SciPy} U{interp2d<https://docs.SciPy.org/
|
|
407
425
|
doc/scipy/reference/generated/scipy.interpolate.interp2d.html>}
|
|
408
|
-
C{kind='linear'}.
|
|
426
|
+
C{kind='linear'} or U{bisplrep/-ev<https://docs.SciPy.org/doc/scipy/
|
|
427
|
+
reference/generated/scipy.interpolate.interp2d.html>} C{kx=ky=1}.
|
|
409
428
|
'''
|
|
410
|
-
_kind =
|
|
429
|
+
_kind = -1
|
|
411
430
|
_kmin = 2
|
|
412
431
|
|
|
413
432
|
def __init__(self, knots, **name_wrap):
|
|
@@ -422,7 +441,7 @@ class HeightLinear(HeightCubic):
|
|
|
422
441
|
height = HeightCubic.height
|
|
423
442
|
|
|
424
443
|
|
|
425
|
-
class HeightLSQBiSpline(
|
|
444
|
+
class HeightLSQBiSpline(_HeightBase):
|
|
426
445
|
'''Height interpolator using C{SciPy} U{LSQSphereBivariateSpline
|
|
427
446
|
<https://docs.SciPy.org/doc/scipy/reference/generated/scipy.
|
|
428
447
|
interpolate.LSQSphereBivariateSpline.html>}.
|
|
@@ -446,13 +465,12 @@ class HeightLSQBiSpline(_HeightsBase):
|
|
|
446
465
|
|
|
447
466
|
@raise LenError: Unequal number of B{C{knots}} and B{C{weight}}s.
|
|
448
467
|
|
|
449
|
-
@raise ImportError: Package C{numpy} or C{scipy} not found or
|
|
450
|
-
|
|
468
|
+
@raise ImportError: Package C{numpy} or C{scipy} not found or not
|
|
469
|
+
installed.
|
|
451
470
|
|
|
452
|
-
@raise SciPyError: A C{scipy}
|
|
471
|
+
@raise SciPyError: A C{scipy} issue.
|
|
453
472
|
|
|
454
|
-
@raise SciPyWarning: A C{scipy}
|
|
455
|
-
warning as exception.
|
|
473
|
+
@raise SciPyWarning: A C{scipy} warning as exception.
|
|
456
474
|
'''
|
|
457
475
|
np = self.numpy
|
|
458
476
|
spi = self.scipy_interpolate
|
|
@@ -465,7 +483,7 @@ class HeightLSQBiSpline(_HeightsBase):
|
|
|
465
483
|
w = float(w)
|
|
466
484
|
if w <= 0:
|
|
467
485
|
raise HeightError(weight=w)
|
|
468
|
-
w =
|
|
486
|
+
w = (w,) * n
|
|
469
487
|
elif w is not None:
|
|
470
488
|
m, w = len2(w)
|
|
471
489
|
if m != n:
|
|
@@ -483,34 +501,17 @@ class HeightLSQBiSpline(_HeightsBase):
|
|
|
483
501
|
self._ev = spi.LSQSphereBivariateSpline(ys, xs, hs,
|
|
484
502
|
ts, ps, eps=EPS, w=w).ev
|
|
485
503
|
except Exception as x:
|
|
486
|
-
raise _SciPyIssue(x)
|
|
504
|
+
raise _SciPyIssue(x, self._ev_name)
|
|
487
505
|
|
|
488
506
|
def __call__(self, *llis, **wrap):
|
|
489
507
|
'''Interpolate the height for one or several locations.
|
|
490
508
|
|
|
491
|
-
@
|
|
492
|
-
|
|
493
|
-
@raise SciPyWarning: A C{scipy} C{LSQSphereBivariateSpline}
|
|
494
|
-
warning as exception.
|
|
495
|
-
|
|
496
|
-
@see: L{Here<_HeightsBase.__call__>} for further details.
|
|
509
|
+
@see: L{Here<_HeightBase.__call__>} for further details.
|
|
497
510
|
'''
|
|
498
|
-
return
|
|
499
|
-
|
|
500
|
-
def height(self, lats, lons, **wrap):
|
|
501
|
-
'''Interpolate the height for one or several lat-/longitudes.
|
|
502
|
-
|
|
503
|
-
@raise SciPyError: A C{scipy} C{LSQSphereBivariateSpline} issue.
|
|
511
|
+
return self._evalls(llis, **wrap)
|
|
504
512
|
|
|
505
|
-
@raise SciPyWarning: A C{scipy} C{LSQSphereBivariateSpline}
|
|
506
|
-
warning as exception.
|
|
507
513
|
|
|
508
|
-
|
|
509
|
-
'''
|
|
510
|
-
return _height_called(self, lats, lons, **wrap)
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
class HeightSmoothBiSpline(_HeightsBase):
|
|
514
|
+
class HeightSmoothBiSpline(_HeightBase):
|
|
514
515
|
'''Height interpolator using C{SciPy} U{SmoothSphereBivariateSpline
|
|
515
516
|
<https://docs.SciPy.org/doc/scipy/reference/generated/scipy.
|
|
516
517
|
interpolate.SmoothSphereBivariateSpline.html>}.
|
|
@@ -527,54 +528,36 @@ class HeightSmoothBiSpline(_HeightsBase):
|
|
|
527
528
|
I{normalize} all B{C{knots}} and B{C{llis}} locations iff
|
|
528
529
|
C{True} (C{bool}).
|
|
529
530
|
|
|
530
|
-
@raise HeightError: Insufficient number of B{C{knots}} or
|
|
531
|
-
|
|
531
|
+
@raise HeightError: Insufficient number of B{C{knots}} or an invalid
|
|
532
|
+
B{C{knot}} or B{C{s}}.
|
|
532
533
|
|
|
533
534
|
@raise ImportError: Package C{numpy} or C{scipy} not found or not
|
|
534
535
|
installed.
|
|
535
536
|
|
|
536
|
-
@raise SciPyError: A C{scipy}
|
|
537
|
+
@raise SciPyError: A C{scipy} issue.
|
|
537
538
|
|
|
538
|
-
@raise SciPyWarning: A C{scipy}
|
|
539
|
-
warning as exception.
|
|
539
|
+
@raise SciPyWarning: A C{scipy} warning as exception.
|
|
540
540
|
'''
|
|
541
541
|
spi = self.scipy_interpolate
|
|
542
542
|
|
|
543
|
-
s = Float_(s,
|
|
543
|
+
s = Float_(smoothing=s, Error=HeightError, low=4)
|
|
544
544
|
|
|
545
545
|
xs, ys, hs = self._xyhs3(knots, **name_wrap)
|
|
546
546
|
try:
|
|
547
547
|
self._ev = spi.SmoothSphereBivariateSpline(ys, xs, hs,
|
|
548
548
|
eps=EPS, s=s).ev
|
|
549
549
|
except Exception as x:
|
|
550
|
-
raise _SciPyIssue(x)
|
|
550
|
+
raise _SciPyIssue(x, self._ev_name)
|
|
551
551
|
|
|
552
552
|
def __call__(self, *llis, **wrap):
|
|
553
553
|
'''Interpolate the height for one or several locations.
|
|
554
554
|
|
|
555
|
-
@
|
|
556
|
-
|
|
557
|
-
@raise SciPyWarning: A C{scipy} C{SmoothSphereBivariateSpline}
|
|
558
|
-
warning as exception.
|
|
559
|
-
|
|
560
|
-
@see: L{Here<_HeightsBase.__call__>} for further details.
|
|
561
|
-
'''
|
|
562
|
-
return _HeightsBase._eval(self, llis, **wrap)
|
|
563
|
-
|
|
564
|
-
def height(self, lats, lons, **wrap):
|
|
565
|
-
'''Interpolate the height for one or several lat-/longitudes.
|
|
566
|
-
|
|
567
|
-
@raise SciPyError: A C{scipy} C{SmoothSphereBivariateSpline} issue.
|
|
568
|
-
|
|
569
|
-
@raise SciPyWarning: A C{scipy} C{SmoothSphereBivariateSpline}
|
|
570
|
-
warning as exception.
|
|
571
|
-
|
|
572
|
-
@see: L{Here<_HeightsBase.height>} for further details.
|
|
555
|
+
@see: L{Here<_HeightBase.__call__>} for further details.
|
|
573
556
|
'''
|
|
574
|
-
return
|
|
557
|
+
return self._evalls(llis, **wrap)
|
|
575
558
|
|
|
576
559
|
|
|
577
|
-
class _HeightIDW(
|
|
560
|
+
class _HeightIDW(_HeightNamed):
|
|
578
561
|
'''(INTERNAL) Base class for U{Inverse Distance Weighting
|
|
579
562
|
<https://WikiPedia.org/wiki/Inverse_distance_weighting>} (IDW) height
|
|
580
563
|
interpolators.
|
|
@@ -608,7 +591,7 @@ class _HeightIDW(_HeightBase):
|
|
|
608
591
|
|
|
609
592
|
n, self._knots = len2(knots)
|
|
610
593
|
if n < self.kmin:
|
|
611
|
-
raise
|
|
594
|
+
raise _InsufficientError(self.kmin, knots=n)
|
|
612
595
|
self.beta = beta
|
|
613
596
|
self._kwds = kwds or {}
|
|
614
597
|
|
|
@@ -684,6 +667,16 @@ class _HeightIDW(_HeightBase):
|
|
|
684
667
|
i = Fmt.INDEX(knots=i)
|
|
685
668
|
raise HeightError(i, k, cause=e)
|
|
686
669
|
|
|
670
|
+
def _distancesTo(self, _To):
|
|
671
|
+
'''(INTERNAL) Yield distances C{_To}.
|
|
672
|
+
'''
|
|
673
|
+
try:
|
|
674
|
+
for i, k in enumerate(self._knots):
|
|
675
|
+
yield _To(k)
|
|
676
|
+
except Exception as e:
|
|
677
|
+
i = Fmt.INDEX(knots=i)
|
|
678
|
+
raise HeightError(i, k, cause=e)
|
|
679
|
+
|
|
687
680
|
def height(self, lats, lons, **wrap):
|
|
688
681
|
'''Interpolate the height for one or several lat-/longitudes.
|
|
689
682
|
|
|
@@ -698,7 +691,8 @@ class _HeightIDW(_HeightBase):
|
|
|
698
691
|
@raise HeightError: Insufficient or non-matching number of B{C{lats}}
|
|
699
692
|
and B{C{lons}} or a L{pygeodesy.fidw} issue.
|
|
700
693
|
'''
|
|
701
|
-
|
|
694
|
+
lls = self._as_lls(lats, lons)
|
|
695
|
+
return self(lls, **wrap) # __call__(ll) or __call__(lls)
|
|
702
696
|
|
|
703
697
|
@Property_RO
|
|
704
698
|
def _heights(self):
|
|
@@ -851,7 +845,7 @@ class HeightIDWdistanceTo(_HeightIDW):
|
|
|
851
845
|
_HeightIDW.__init__(self, knots, beta=beta, **name__distanceTo_kwds)
|
|
852
846
|
ks0 = _distanceTo(HeightError, knots=self._knots)[0]
|
|
853
847
|
# use knots[0] class and datum to create compatible points
|
|
854
|
-
# in
|
|
848
|
+
# in ._as_lls instead of class LatLon_ and datum None
|
|
855
849
|
self._datum = ks0.datum
|
|
856
850
|
self._LLis = ks0.classof # type(ks0)
|
|
857
851
|
|
|
@@ -859,12 +853,11 @@ class HeightIDWdistanceTo(_HeightIDW):
|
|
|
859
853
|
'''(INTERNAL) Yield distances to C{(x, y)}.
|
|
860
854
|
'''
|
|
861
855
|
kwds, ll = self._kwds, self._LLis(y, x)
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
raise HeightError(i, k, cause=e)
|
|
856
|
+
|
|
857
|
+
def _To(k):
|
|
858
|
+
return k.distanceTo(ll, **kwds)
|
|
859
|
+
|
|
860
|
+
return self._distancesTo(_To)
|
|
868
861
|
|
|
869
862
|
if _FOR_DOCS:
|
|
870
863
|
__call__ = _HeightIDW.__call__
|
|
@@ -892,12 +885,11 @@ class HeightIDWequirectangular(_HeightIDW):
|
|
|
892
885
|
'''(INTERNAL) Yield distances to C{(x, y)}.
|
|
893
886
|
'''
|
|
894
887
|
_f, kwds = _formy.equirectangular4, self._kwds
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
raise HeightError(i, k, cause=e)
|
|
888
|
+
|
|
889
|
+
def _To(k):
|
|
890
|
+
return _f(y, x, k.lat, k.lon, **kwds).distance2
|
|
891
|
+
|
|
892
|
+
return self._distancesTo(_To)
|
|
901
893
|
|
|
902
894
|
if _FOR_DOCS:
|
|
903
895
|
__call__ = _HeightIDW.__call__
|
|
@@ -1114,7 +1106,7 @@ class HeightIDWvincentys(_HeightIDW):
|
|
|
1114
1106
|
height = _HeightIDW.height
|
|
1115
1107
|
|
|
1116
1108
|
|
|
1117
|
-
__all__ += _ALL_DOCS(_HeightBase, _HeightIDW,
|
|
1109
|
+
__all__ += _ALL_DOCS(_HeightBase, _HeightIDW, _HeightNamed)
|
|
1118
1110
|
|
|
1119
1111
|
# **) MIT License
|
|
1120
1112
|
#
|
pygeodesy/internals.py
CHANGED
|
@@ -18,6 +18,7 @@ _0_0 = 0.0 # PYCHOK in .basics, .constants
|
|
|
18
18
|
_arm64_ = 'arm64'
|
|
19
19
|
_iOS_ = 'iOS'
|
|
20
20
|
_macOS_ = 'macOS'
|
|
21
|
+
_SIsecs = 'fs', 'ps', 'ns', 'us', 'ms', 'sec' # reversed
|
|
21
22
|
_Windows_ = 'Windows'
|
|
22
23
|
|
|
23
24
|
|
|
@@ -206,6 +207,13 @@ class _MODS_Base(object):
|
|
|
206
207
|
l3.insert(0, pypy)
|
|
207
208
|
return l3
|
|
208
209
|
|
|
210
|
+
@_Property_RO
|
|
211
|
+
def _Str_Bytes(self):
|
|
212
|
+
'''Get all C{str} and C{bytes} types.
|
|
213
|
+
'''
|
|
214
|
+
import pygeodesy.basics as m
|
|
215
|
+
return m._Strs + m._Bytes # + (range, map)
|
|
216
|
+
|
|
209
217
|
@_Property_RO
|
|
210
218
|
def streprs(self):
|
|
211
219
|
'''Get module C{pygeodesy.streprs}, I{once}.
|
|
@@ -253,6 +261,12 @@ def _enquote(strs, quote=_QUOTE2_, white=NN): # in .basics, .solveBase
|
|
|
253
261
|
return strs
|
|
254
262
|
|
|
255
263
|
|
|
264
|
+
def _fper(p, q, per=100.0, prec=1):
|
|
265
|
+
'''Format a percentage C{B{p} * B{per} / B{q}} (C{str}).
|
|
266
|
+
'''
|
|
267
|
+
return '%.*f%%' % (prec, (float(p) * per / float(q)))
|
|
268
|
+
|
|
269
|
+
|
|
256
270
|
def _headof(name):
|
|
257
271
|
'''(INTERNAL) Get the head name of qualified C{name} or the C{name}.
|
|
258
272
|
'''
|
|
@@ -291,6 +305,13 @@ def _isNix(): # in test/bases.py
|
|
|
291
305
|
return _MODS.nix2[0]
|
|
292
306
|
|
|
293
307
|
|
|
308
|
+
def _isPyChecker():
|
|
309
|
+
'''(INTERNAL) Is C{PyChecker} running? (C{bool}).
|
|
310
|
+
'''
|
|
311
|
+
# .../pychecker/checker.py --limit 0 --stdlib pygeodesy/<mod>/<name>.py
|
|
312
|
+
return _sys.argv[0].endswith('/pychecker/checker.py')
|
|
313
|
+
|
|
314
|
+
|
|
294
315
|
def _isPyPy(): # in test/bases.py
|
|
295
316
|
'''(INTERNAL) Is this C{PyPy}? (C{bool})
|
|
296
317
|
'''
|
|
@@ -342,12 +363,30 @@ def machine():
|
|
|
342
363
|
return _MODS.bits_machine2[1]
|
|
343
364
|
|
|
344
365
|
|
|
366
|
+
def _Math_K_2():
|
|
367
|
+
'''(INTERNAL) Return the I{Karney} Math setting.
|
|
368
|
+
'''
|
|
369
|
+
return _MODS.karney._wrapped.Math_K_2
|
|
370
|
+
|
|
371
|
+
|
|
345
372
|
def _name_version(pkg):
|
|
346
373
|
'''(INTERNAL) Return C{pskg.__name__ + ' ' + .__version__}.
|
|
347
374
|
'''
|
|
348
375
|
return _SPACE_(pkg.__name__, pkg.__version__)
|
|
349
376
|
|
|
350
377
|
|
|
378
|
+
def _name_binary(path):
|
|
379
|
+
'''(INTERNAL) Return C{(basename + ' ' + version)} of an executable.
|
|
380
|
+
'''
|
|
381
|
+
if path:
|
|
382
|
+
try:
|
|
383
|
+
_, r = _MODS.solveBase._popen2((path, '--version'))
|
|
384
|
+
return _SPACE_(_os_path.basename(path), r.split()[-1])
|
|
385
|
+
except (IndexError, IOError, OSError):
|
|
386
|
+
pass
|
|
387
|
+
return NN
|
|
388
|
+
|
|
389
|
+
|
|
351
390
|
def _osversion2(sep=NN): # in .lazily, test/bases.versions
|
|
352
391
|
'''(INTERNAL) Get the O/S name and release as C{2-list} or C{str}.
|
|
353
392
|
'''
|
|
@@ -443,15 +482,36 @@ def _Pythonarchine(sep=NN): # in .lazily, test/bases.py versions
|
|
|
443
482
|
return sep.join(l3) if sep else l3 # 3- or 4-list
|
|
444
483
|
|
|
445
484
|
|
|
446
|
-
def
|
|
485
|
+
def _secs2str(secs): # in .geoids, ../test/bases.py
|
|
486
|
+
'''Convert a time in C{secs} to C{str}.
|
|
487
|
+
'''
|
|
488
|
+
if secs < _MODS.constants._100_0:
|
|
489
|
+
unit = len(_SIsecs) - 1
|
|
490
|
+
while 0 < secs < 1 and unit > 0:
|
|
491
|
+
secs *= 1e3 # _1000_0
|
|
492
|
+
unit -= 1
|
|
493
|
+
t = '%.3f %s' % (secs, _SIsecs[unit])
|
|
494
|
+
else:
|
|
495
|
+
m, s = divmod(secs, 60)
|
|
496
|
+
if m < 60:
|
|
497
|
+
t = '%d:%06.3f' % (int(m), s)
|
|
498
|
+
else:
|
|
499
|
+
h, m = divmod(int(m), 60)
|
|
500
|
+
t = '%d:%02d:%06.3f' % (h, m, s)
|
|
501
|
+
return t
|
|
502
|
+
|
|
503
|
+
|
|
504
|
+
def _sizeof(obj, deep=True):
|
|
447
505
|
'''(INTERNAL) Recursively size an C{obj}ect.
|
|
448
506
|
|
|
449
|
-
@
|
|
450
|
-
|
|
451
|
-
counting duplicates only once or
|
|
452
|
-
C{None}.
|
|
507
|
+
@kwarg deep: If C{True}, include the size of all
|
|
508
|
+
C{.__dict__.values()} (C{bool}).
|
|
453
509
|
|
|
454
|
-
@
|
|
510
|
+
@return: The C{obj} size in bytes (C{int}), ignoring
|
|
511
|
+
class attributes and counting instances only
|
|
512
|
+
once or C{None}.
|
|
513
|
+
|
|
514
|
+
@note: With C{PyPy}, the returned size is always C{None}.
|
|
455
515
|
'''
|
|
456
516
|
try:
|
|
457
517
|
_zB = _sys.getsizeof
|
|
@@ -471,9 +531,10 @@ def _sizeof(obj):
|
|
|
471
531
|
if isinstance(o, dict):
|
|
472
532
|
z += _zR(s, o.keys())
|
|
473
533
|
z += _zR(s, o.values())
|
|
474
|
-
elif _isiterablen(o)
|
|
534
|
+
elif _isiterablen(o) and not \
|
|
535
|
+
isinstance(o, _MODS._Str_Bytes):
|
|
475
536
|
z += _zR(s, o)
|
|
476
|
-
|
|
537
|
+
elif deep:
|
|
477
538
|
try: # size instance' attr values only
|
|
478
539
|
z += _zR(s, o.__dict__.values())
|
|
479
540
|
except AttributeError: # None, int, etc.
|
|
@@ -591,7 +652,7 @@ def _versions(sep=_SPACE_):
|
|
|
591
652
|
|
|
592
653
|
|
|
593
654
|
__all__ = tuple(map(_dunder_nameof, (machine, print_, printf)))
|
|
594
|
-
__version__ = '24.
|
|
655
|
+
__version__ = '24.09.04'
|
|
595
656
|
|
|
596
657
|
if _dunder_ismain(__name__): # PYCHOK no cover
|
|
597
658
|
|