pygeodesy 25.12.31__py2.py3-none-any.whl → 26.2.2__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/__init__.py +9 -9
- pygeodesy/albers.py +5 -5
- pygeodesy/auxilats/auxDLat.py +2 -3
- pygeodesy/auxilats/auxLat.py +7 -8
- pygeodesy/cartesianBase.py +2 -2
- pygeodesy/constants.py +6 -1
- pygeodesy/datums.py +5 -8
- pygeodesy/ellipsoids.py +9 -8
- pygeodesy/elliptic.py +543 -149
- pygeodesy/fmath.py +2 -2
- pygeodesy/formy.py +10 -249
- pygeodesy/fsums.py +43 -27
- pygeodesy/geod3solve.py +18 -3
- pygeodesy/geoids.py +120 -73
- pygeodesy/heights.py +8 -7
- pygeodesy/internals.py +10 -3
- pygeodesy/lazily.py +13 -6
- pygeodesy/lcc.py +3 -7
- pygeodesy/named.py +13 -9
- pygeodesy/trf.py +1 -1
- pygeodesy/triaxials/bases.py +64 -42
- pygeodesy/triaxials/triaxial3.py +40 -43
- pygeodesy/triaxials/triaxial5.py +17 -49
- pygeodesy/utily.py +7 -7
- {pygeodesy-25.12.31.dist-info → pygeodesy-26.2.2.dist-info}/METADATA +10 -10
- {pygeodesy-25.12.31.dist-info → pygeodesy-26.2.2.dist-info}/RECORD +28 -28
- {pygeodesy-25.12.31.dist-info → pygeodesy-26.2.2.dist-info}/WHEEL +0 -0
- {pygeodesy-25.12.31.dist-info → pygeodesy-26.2.2.dist-info}/top_level.txt +0 -0
pygeodesy/geoids.py
CHANGED
|
@@ -89,18 +89,17 @@ courtesy of SBFRF.
|
|
|
89
89
|
# make sure int/int division yields float quotient, see .basics
|
|
90
90
|
from __future__ import division as _; del _ # noqa: E702 ;
|
|
91
91
|
|
|
92
|
-
from pygeodesy.basics import _isin, len2, min2, isodd, _splituple
|
|
93
|
-
ub2str as _ub2str
|
|
92
|
+
from pygeodesy.basics import _isin, len2, min2, isodd, _splituple
|
|
94
93
|
from pygeodesy.constants import EPS, _float as _F, _1_0, _N_90_0, _180_0, \
|
|
95
94
|
_N_180_0, _360_0
|
|
96
95
|
from pygeodesy.datums import Datums, _ellipsoidal_datum, _WGS84
|
|
97
96
|
# from pygeodesy.dms import parseDMS2 # _MODS
|
|
98
97
|
from pygeodesy.errors import _incompatible, LenError, RangeError, _SciPyIssue, \
|
|
99
98
|
_xkwds_pop2
|
|
100
|
-
from pygeodesy.fmath import favg,
|
|
99
|
+
from pygeodesy.fmath import favg, frange, Fsum
|
|
101
100
|
# from pygoedesy.formy import heightOrthometric # _MODS
|
|
102
|
-
from pygeodesy.
|
|
103
|
-
|
|
101
|
+
# from pygeodesy.fsums import Fsum # from .fmath
|
|
102
|
+
from pygeodesy.heights import _as_llis2, _ascalar, _HeightBase, HeightError, _Wrap
|
|
104
103
|
# from pygeodesy.internals import typename, _version2 # _MODS
|
|
105
104
|
from pygeodesy.interns import NN, _COLONSPACE_, _COMMASPACE_, _DMAIN_, _E_, \
|
|
106
105
|
_height_, _in_, _kind_, _lat_, _lon_, _mean_, _N_, \
|
|
@@ -115,8 +114,8 @@ from pygeodesy.units import Height, Int_, Lat, Lon
|
|
|
115
114
|
# from pygeodesy.utily import _Wrap # from .heights
|
|
116
115
|
|
|
117
116
|
from math import floor as _floor
|
|
118
|
-
#
|
|
119
|
-
# import os.path #
|
|
117
|
+
# import os as _os # _MODS
|
|
118
|
+
# import os.path # _os.path
|
|
120
119
|
from struct import calcsize as _calcsize, unpack as _unpack
|
|
121
120
|
try:
|
|
122
121
|
from StringIO import StringIO as _BytesIO # reads bytes
|
|
@@ -124,9 +123,10 @@ try:
|
|
|
124
123
|
|
|
125
124
|
except ImportError: # Python 3+
|
|
126
125
|
from io import BytesIO as _BytesIO # PYCHOK expected
|
|
126
|
+
from pygeodesy.basics import ub2str as _ub2str
|
|
127
127
|
|
|
128
128
|
__all__ = _ALL_LAZY.geoids
|
|
129
|
-
__version__ = '
|
|
129
|
+
__version__ = '26.02.02'
|
|
130
130
|
|
|
131
131
|
_assert_ = 'assert'
|
|
132
132
|
_bHASH_ = b'#'
|
|
@@ -135,9 +135,50 @@ _format_ = '%s %r'
|
|
|
135
135
|
_header_ = 'header'
|
|
136
136
|
_intCs = {} # cache int value, del below
|
|
137
137
|
_lli_ = 'lli'
|
|
138
|
+
_os = _MODS.os
|
|
138
139
|
_rb_ = 'rb'
|
|
139
140
|
_supported_ = 'supported'
|
|
140
141
|
|
|
142
|
+
if __debug__:
|
|
143
|
+
from pygeodesy.fmath import Fdot as _Dotf, Fhorner as _Hornerf
|
|
144
|
+
|
|
145
|
+
else: # -OO ... runs GeoidKarney 8+X faster (w/o Fwelford)
|
|
146
|
+
from pygeodesy.fsums import _fsum
|
|
147
|
+
from operator import mul as _mul
|
|
148
|
+
|
|
149
|
+
class _GKsum(Fsum): # for GeoidKarney only
|
|
150
|
+
|
|
151
|
+
def __iadd__(self, other):
|
|
152
|
+
xs = other._ps if isinstance(other, _GKsum) else (other,)
|
|
153
|
+
self._ps_acc(self._ps, xs, up=False)
|
|
154
|
+
return self
|
|
155
|
+
|
|
156
|
+
def __imul__(self, x):
|
|
157
|
+
self._ps[:] = (x * p for p in self._ps)
|
|
158
|
+
return self
|
|
159
|
+
|
|
160
|
+
fmul = __imul__ # like .fsums.Fsum
|
|
161
|
+
|
|
162
|
+
def fsum(self): # PYCHOK signature
|
|
163
|
+
return _fsum(self._ps)
|
|
164
|
+
|
|
165
|
+
class _Dotf(_GKsum): # PYCHOK redef
|
|
166
|
+
'''Fast precision dot product M{sum(a[i] * b[i] for i=0..len(a))}
|
|
167
|
+
but for C{float} C{a} and C{b} only.
|
|
168
|
+
'''
|
|
169
|
+
def __init__(self, a, *b):
|
|
170
|
+
self._ps = self._ps_acc([], map(_mul, a, b), up=False)
|
|
171
|
+
|
|
172
|
+
class _Hornerf(_GKsum): # PYCHOK redef
|
|
173
|
+
'''Fast polynomial evaluation M{sum(cs[i] * x**i for i=0..len(cs))}
|
|
174
|
+
but for C{float} C{x} and C{cs} and C{incx=True} only.
|
|
175
|
+
'''
|
|
176
|
+
def __init__(self, x, *cs): # incx=True
|
|
177
|
+
self._ps = []
|
|
178
|
+
for c in reversed(cs): # multiply-accumulate
|
|
179
|
+
self *= x # ps[:] = (x * p for p in ps)
|
|
180
|
+
self += c # self._ps_acc(ps, (c,), up=False)
|
|
181
|
+
|
|
141
182
|
|
|
142
183
|
class GeoidError(HeightError):
|
|
143
184
|
'''Geoid interpolator C{Geoid...} or interpolation issue.
|
|
@@ -484,7 +525,7 @@ class _GeoidBase(_HeightBase):
|
|
|
484
525
|
|
|
485
526
|
def _load(self, g, dtype=float, n=-1, offset=0, **sep): # sep=NN
|
|
486
527
|
# numpy.fromfile, like .frombuffer
|
|
487
|
-
g.seek(offset,
|
|
528
|
+
g.seek(offset, _os.SEEK_SET)
|
|
488
529
|
return self.numpy.fromfile(g, dtype, count=n, **sep)
|
|
489
530
|
|
|
490
531
|
@Property_RO
|
|
@@ -566,8 +607,8 @@ class _GeoidBase(_HeightBase):
|
|
|
566
607
|
def _open(self, geoid, datum, kind, name, smooth):
|
|
567
608
|
# open the geoid file
|
|
568
609
|
try:
|
|
569
|
-
self._geoid =
|
|
570
|
-
self._sizeB =
|
|
610
|
+
self._geoid = _os.path.basename(geoid)
|
|
611
|
+
self._sizeB = _os.path.getsize(geoid)
|
|
571
612
|
g = open(geoid, _rb_)
|
|
572
613
|
except (IOError, OSError) as x:
|
|
573
614
|
raise GeoidError(geoid=geoid, cause=x)
|
|
@@ -774,15 +815,11 @@ class GeoidEGM96(_GeoidBase):
|
|
|
774
815
|
|
|
775
816
|
def _g2ll2(self, lat, lon):
|
|
776
817
|
# convert grid (lat, lon) to earth (lat, lon)
|
|
777
|
-
|
|
778
|
-
lon -= _360_0
|
|
779
|
-
return -lat, lon # invert lat
|
|
818
|
+
return -lat, _lonE2lon(lon) # invert lat
|
|
780
819
|
|
|
781
820
|
def _ll2g2(self, lat, lon):
|
|
782
821
|
# convert earth (lat, lon) to grid (lat, lon)
|
|
783
|
-
|
|
784
|
-
lon += _360_0
|
|
785
|
-
return -lat, lon # invert lat
|
|
822
|
+
return -lat, _lon2lonE(lon) # invert lat
|
|
786
823
|
|
|
787
824
|
if _FOR_DOCS:
|
|
788
825
|
__call__ = _GeoidBase.__call__
|
|
@@ -791,29 +828,27 @@ class GeoidEGM96(_GeoidBase):
|
|
|
791
828
|
|
|
792
829
|
class GeoidG2012B(_GeoidBase):
|
|
793
830
|
'''Geoid height interpolator for U{GEOID12B Model
|
|
794
|
-
<https://
|
|
795
|
-
<https://
|
|
796
|
-
U{Alaska<https://
|
|
797
|
-
U{Hawaii<https://
|
|
831
|
+
<https://Geodesy.NOAA.gov/GEOID/GEOID12B/>} grids U{CONUS
|
|
832
|
+
<https://Geodesy.NOAA.gov/GEOID/GEOID12B/GEOID12B_CONUS.shtml>},
|
|
833
|
+
U{Alaska<https://Geodesy.NOAA.gov/GEOID/GEOID12B/GEOID12B_AK.shtml>},
|
|
834
|
+
U{Hawaii<https://Geodesy.NOAA.gov/GEOID/GEOID12B/GEOID12B_HI.shtml>},
|
|
798
835
|
U{Guam and Northern Mariana Islands
|
|
799
|
-
<https://
|
|
836
|
+
<https://Geodesy.NOAA.gov/GEOID/GEOID12B/GEOID12B_GMNI.shtml>},
|
|
800
837
|
U{Puerto Rico and U.S. Virgin Islands
|
|
801
|
-
<https://
|
|
802
|
-
U{American Samoa<https://
|
|
838
|
+
<https://Geodesy.NOAA.gov/GEOID/GEOID12B/GEOID12B_PRVI.shtml>} and
|
|
839
|
+
U{American Samoa<https://Geodesy.NOAA.gov/GEOID/GEOID12B/GEOID12B_AS.shtml>}
|
|
803
840
|
based on C{SciPy} interpolation U{RectBivariateSpline<https://docs.SciPy.org/doc/
|
|
804
841
|
scipy/reference/generated/scipy.interpolate.RectBivariateSpline.html>}, U{interp2d
|
|
805
842
|
<https://docs.SciPy.org/doc/scipy/reference/generated/scipy.interpolate.interp2d.html>}
|
|
806
843
|
or U{bisplrep/-ev<https://docs.scipy.org/doc/scipy/reference/generated/scipy.interpolate.
|
|
807
844
|
bisplrep.html>}.
|
|
808
|
-
|
|
809
|
-
Use any of the C{le} (little endian) or C{be} (big endian) C{g2012b*.bin} binary grid files.
|
|
810
845
|
'''
|
|
811
846
|
_datum = Datums.NAD83
|
|
812
847
|
|
|
813
848
|
def __init__(self, g2012b_bin, datum=Datums.NAD83, kind=3, smooth=0, **name_crop):
|
|
814
849
|
'''New L{GeoidG2012B} interpolator.
|
|
815
850
|
|
|
816
|
-
@arg g2012b_bin: A C{GEOID12B} grid file name (C{.bin}).
|
|
851
|
+
@arg g2012b_bin: A C{GEOID12B} grid file name (C{.bin}, see B{note}).
|
|
817
852
|
@kwarg datum: Optional grid datum (L{Datum}, L{Ellipsoid}, L{Ellipsoid2} or
|
|
818
853
|
L{a_f2Tuple}), overriding C{NAD83}.
|
|
819
854
|
@kwarg kind: C{scipy.interpolate} order (C{int}), use 1..5 for U{RectBivariateSpline
|
|
@@ -827,8 +862,8 @@ class GeoidG2012B(_GeoidBase):
|
|
|
827
862
|
@kwarg name_crop: Optional geoid C{B{name}=NN} (C{str}) and UNSUPPORTED keyword argument
|
|
828
863
|
C{B{crop}=None}.
|
|
829
864
|
|
|
830
|
-
@raise GeoidError: Invalid B{C{crop}}, B{C{kind}} or B{C{smooth}} or a
|
|
831
|
-
|
|
865
|
+
@raise GeoidError: Invalid B{C{crop}}, B{C{kind}} or B{C{smooth}} or a B{C{g2012b_bin}}
|
|
866
|
+
grid file issue.
|
|
832
867
|
|
|
833
868
|
@raise ImportError: Package C{numpy} or C{scipy} not found or not installed.
|
|
834
869
|
|
|
@@ -840,8 +875,11 @@ class GeoidG2012B(_GeoidBase):
|
|
|
840
875
|
|
|
841
876
|
@raise TypeError: Invalid B{C{datum}}.
|
|
842
877
|
|
|
843
|
-
@note:
|
|
844
|
-
|
|
878
|
+
@note: Only use any of the C{le} (little-endian) or C{be} (big-endian) C{g2012b*.bin}
|
|
879
|
+
I{binary} grid files.
|
|
880
|
+
|
|
881
|
+
@note: Specify C{B{kind}=-1, -3 or -5} to use C{scipy.interpolate.interp2d} I{before}
|
|
882
|
+
or C{scipy.interpolate.bisplrep/-ev} I{since} C{Scipy} version 1.14.
|
|
845
883
|
'''
|
|
846
884
|
crop, name = _xkwds_pop2(name_crop, crop=None)
|
|
847
885
|
if crop is not None:
|
|
@@ -871,7 +909,7 @@ class GeoidG2012B(_GeoidBase):
|
|
|
871
909
|
p.slat, p.wlon, p.dlat, p.dlon = map(float, self._load(g, en_+'f8', 4))
|
|
872
910
|
# read all f4 heights, ignoring the first 4xf8 and 3xi4
|
|
873
911
|
hs = self._load(g, self._endian, n, 44).reshape(p.nlat, p.nlon)
|
|
874
|
-
p.wlon -= _360_0 # western-most
|
|
912
|
+
p.wlon -= _360_0 # western-most lon XXX _lonE2lon
|
|
875
913
|
_GeoidBase.__init__(self, hs, p)
|
|
876
914
|
|
|
877
915
|
except Exception as x:
|
|
@@ -975,12 +1013,12 @@ class GeoidKarney(_GeoidBase):
|
|
|
975
1013
|
_CM = (_T(' 0, -1'), # 10x12 cubic matrix [i, j] indices
|
|
976
1014
|
_T(' 1, -1'),
|
|
977
1015
|
_T('-1, 0'),
|
|
978
|
-
_T(' 0, 0'),
|
|
979
|
-
_T(' 1, 0'),
|
|
1016
|
+
_T(' 0, 0'), # _BT[0]
|
|
1017
|
+
_T(' 1, 0'), # _BT[1]
|
|
980
1018
|
_T(' 2, 0'),
|
|
981
1019
|
_T('-1, 1'),
|
|
982
|
-
_T(' 0, 1'),
|
|
983
|
-
_T(' 1, 1'),
|
|
1020
|
+
_T(' 0, 1'), # _BT[2]
|
|
1021
|
+
_T(' 1, 1'), # _BT[3]
|
|
984
1022
|
_T(' 2, 1'),
|
|
985
1023
|
_T(' 0, 2'),
|
|
986
1024
|
_T(' 1, 2'))
|
|
@@ -1063,7 +1101,7 @@ class GeoidKarney(_GeoidBase):
|
|
|
1063
1101
|
p = self._pgm
|
|
1064
1102
|
if 0 < x < (p.nlon - 2) and 0 < y < (p.nlat - 2):
|
|
1065
1103
|
# read 4x4 ushorts, drop the 4 corners
|
|
1066
|
-
S =
|
|
1104
|
+
S = _os.SEEK_SET
|
|
1067
1105
|
e = self._4endian
|
|
1068
1106
|
g = self._egm
|
|
1069
1107
|
n = self._4u2B
|
|
@@ -1099,7 +1137,7 @@ class GeoidKarney(_GeoidBase):
|
|
|
1099
1137
|
y, x = int(_floor(fy)), int(_floor(fx))
|
|
1100
1138
|
fy -= y
|
|
1101
1139
|
fx -= x
|
|
1102
|
-
H = self._ev2d(fy, fx, y, x) # PYCHOK .
|
|
1140
|
+
H = self._ev2d(fy, fx, y, x) # PYCHOK ._ev3k or ._ev2k
|
|
1103
1141
|
H *= self._pgm.Scale # H.fmul(self._pgm.Scale)
|
|
1104
1142
|
H += self._pgm.Offset # H.fadd(self._pgm.Offset)
|
|
1105
1143
|
return H.fsum() # float(H)
|
|
@@ -1112,10 +1150,10 @@ class GeoidKarney(_GeoidBase):
|
|
|
1112
1150
|
y, x = self._yx_i = yx
|
|
1113
1151
|
self._yx_t = self._raws(y, x, GeoidKarney._BT)
|
|
1114
1152
|
t = self._yx_t
|
|
1115
|
-
v = _1_0, -fx, fx
|
|
1116
|
-
H =
|
|
1117
|
-
H +=
|
|
1118
|
-
return H
|
|
1153
|
+
v = _1_0, (-fx), fx
|
|
1154
|
+
H = _Dotf(v, t[0], t[0], t[1]).fmul(_1_0 - fy) # c = a * (1 - fy)
|
|
1155
|
+
H += _Dotf(v, t[2], t[2], t[3]).fmul(fy) # c += b * fy
|
|
1156
|
+
return H # Fsum
|
|
1119
1157
|
|
|
1120
1158
|
def _ev3k(self, fy, fx, *yx):
|
|
1121
1159
|
# compute the cubic 10-tuple and interpolate raw H
|
|
@@ -1124,7 +1162,7 @@ class GeoidKarney(_GeoidBase):
|
|
|
1124
1162
|
else:
|
|
1125
1163
|
c0, c3, v = self._c0c3v(*yx)
|
|
1126
1164
|
# assert len(c3) == self._nterms
|
|
1127
|
-
self._yx_t = tuple(
|
|
1165
|
+
self._yx_t = tuple(_Dotf(v, *r3).fover(c0) for r3 in c3)
|
|
1128
1166
|
self._yx_i = yx
|
|
1129
1167
|
# GeographicLib/Geoid.cpp Geoid::height(lat, lon) ...
|
|
1130
1168
|
# real h = t[0] + fx * (t[1] + fx * (t[3] + fx * t[6])) +
|
|
@@ -1132,20 +1170,18 @@ class GeoidKarney(_GeoidBase):
|
|
|
1132
1170
|
# fy * (t[5] + fx * t[8] + fy * t[9]));
|
|
1133
1171
|
t = self._yx_t
|
|
1134
1172
|
v = _1_0, fx, fy
|
|
1135
|
-
H =
|
|
1136
|
-
H *=
|
|
1137
|
-
H +=
|
|
1138
|
-
H *=
|
|
1139
|
-
H +=
|
|
1140
|
-
return H
|
|
1173
|
+
H = _Dotf(v, t[5], t[8], t[9])
|
|
1174
|
+
H *= fy
|
|
1175
|
+
H += _Hornerf(fx, t[2], t[4], t[7])
|
|
1176
|
+
H *= fy
|
|
1177
|
+
H += _Hornerf(fx, t[0], t[1], t[3], t[6])
|
|
1178
|
+
return H # Fsum
|
|
1141
1179
|
|
|
1142
1180
|
_ev2d = _ev3k # overriden for kind=2, see ._ev_name
|
|
1143
1181
|
|
|
1144
1182
|
def _g2ll2(self, lat, lon):
|
|
1145
1183
|
# convert grid (lat, lon) to earth (lat, lon), uncropped
|
|
1146
|
-
|
|
1147
|
-
lon -= _360_0
|
|
1148
|
-
return lat, lon
|
|
1184
|
+
return lat, _lonE2lon(lon)
|
|
1149
1185
|
|
|
1150
1186
|
def _g2yx2(self, lat, lon):
|
|
1151
1187
|
# convert grid (lat, lon) to grid (y, x) indices
|
|
@@ -1188,9 +1224,7 @@ class GeoidKarney(_GeoidBase):
|
|
|
1188
1224
|
|
|
1189
1225
|
def _ll2g2(self, lat, lon):
|
|
1190
1226
|
# convert earth (lat, lon) to grid (lat, lon), uncropped
|
|
1191
|
-
|
|
1192
|
-
lon += _360_0
|
|
1193
|
-
return lat, lon
|
|
1227
|
+
return lat, _lon2lonE(lon)
|
|
1194
1228
|
|
|
1195
1229
|
def _llh3minmax(self, highest, *lat2):
|
|
1196
1230
|
# find highest or lowest, takes 10+ secs for egm2008-1.pgm geoid
|
|
@@ -1277,7 +1311,7 @@ class GeoidKarney(_GeoidBase):
|
|
|
1277
1311
|
p, g = self._pgm, self._egm
|
|
1278
1312
|
if g:
|
|
1279
1313
|
b = p.skip + (y * p.nlon + x) * self._u2B
|
|
1280
|
-
g.seek(b,
|
|
1314
|
+
g.seek(b, _os.SEEK_SET)
|
|
1281
1315
|
return b # position
|
|
1282
1316
|
raise GeoidError('closed file', txt=repr(p.egm)) # IOError
|
|
1283
1317
|
|
|
@@ -1347,7 +1381,7 @@ class GeoidPGM(_GeoidBase):
|
|
|
1347
1381
|
the available memory, especially with 32-bit Python. To reduce memory
|
|
1348
1382
|
usage, set keyword argument B{C{crop}} to the region of interest. For
|
|
1349
1383
|
example C{B{crop}=(20, -125, 50, -65)} covers the U{conterminous US
|
|
1350
|
-
<https://
|
|
1384
|
+
<https://Geodesy.NOAA.gov/GEOID/GEOID12B/maps/GEOID12B_CONUS_grids.png>}
|
|
1351
1385
|
(CONUS), less than 3% of the entire C{egm2008-1.pgm} dataset.
|
|
1352
1386
|
|
|
1353
1387
|
@see: Class L{GeoidKarney} and function L{egmGeoidHeights}.
|
|
@@ -1382,8 +1416,7 @@ class GeoidPGM(_GeoidBase):
|
|
|
1382
1416
|
if self._cropped:
|
|
1383
1417
|
lon -= self._lon_of
|
|
1384
1418
|
else:
|
|
1385
|
-
|
|
1386
|
-
lon -= _360_0
|
|
1419
|
+
lon = _lonE2lon(lon)
|
|
1387
1420
|
return lat, lon
|
|
1388
1421
|
|
|
1389
1422
|
def _ll2g2(self, lat, lon):
|
|
@@ -1391,8 +1424,7 @@ class GeoidPGM(_GeoidBase):
|
|
|
1391
1424
|
if self._cropped:
|
|
1392
1425
|
lon += self._lon_of
|
|
1393
1426
|
else:
|
|
1394
|
-
|
|
1395
|
-
lon += _360_0
|
|
1427
|
+
lon = _lon2lonE(lon)
|
|
1396
1428
|
return lat, lon
|
|
1397
1429
|
|
|
1398
1430
|
if _FOR_DOCS:
|
|
@@ -1541,8 +1573,8 @@ class _PGM(_Gpars):
|
|
|
1541
1573
|
self.slat, self.wlon = self.Origin
|
|
1542
1574
|
# note, negative .dlat and .rlat since rows
|
|
1543
1575
|
# are from .slat 90N down in decreasing lat
|
|
1544
|
-
self.dlat, self.dlon = _180_0 / (1 - nlat), _360_0 / nlon
|
|
1545
|
-
self.rlat, self.rlon = (1 - nlat) / _180_0, nlon / _360_0
|
|
1576
|
+
self.dlat, self.dlon = (_180_0 / (1 - nlat)), (_360_0 / nlon)
|
|
1577
|
+
self.rlat, self.rlon = ((1 - nlat) / _180_0), (nlon / _360_0)
|
|
1546
1578
|
|
|
1547
1579
|
# grid corners in earth (lat, lon), .slat = 90, .dlat < 0
|
|
1548
1580
|
n = float(self.slat)
|
|
@@ -1604,11 +1636,11 @@ class _PGM(_Gpars):
|
|
|
1604
1636
|
t, c = 0, self._tmpfile()
|
|
1605
1637
|
# reading (s - n) rows, forward
|
|
1606
1638
|
for y in range(n, s): # PYCHOK y unused
|
|
1607
|
-
g.seek(z,
|
|
1639
|
+
g.seek(z, _os.SEEK_SET)
|
|
1608
1640
|
# Python 2 tmpfile.write returns None
|
|
1609
1641
|
t += c.write(g.read(r)) or r
|
|
1610
1642
|
if p: # wrap around to start of row
|
|
1611
|
-
g.seek(-q,
|
|
1643
|
+
g.seek(-q, _os.SEEK_CUR)
|
|
1612
1644
|
# assert(g.tell() == (z - w * self.u2B))
|
|
1613
1645
|
# Python 2 tmpfile.write returns None
|
|
1614
1646
|
t += c.write(g.read(p)) or p
|
|
@@ -1635,7 +1667,7 @@ class _PGM(_Gpars):
|
|
|
1635
1667
|
self.knots = k
|
|
1636
1668
|
self.skip = 0 # no header lines in c
|
|
1637
1669
|
|
|
1638
|
-
c.seek(0,
|
|
1670
|
+
c.seek(0, _os.SEEK_SET)
|
|
1639
1671
|
# c = open(c.name, _rb_) # reopen for numpy 1.8.0-
|
|
1640
1672
|
return c
|
|
1641
1673
|
|
|
@@ -1659,11 +1691,11 @@ class _PGM(_Gpars):
|
|
|
1659
1691
|
try:
|
|
1660
1692
|
from tempfile import NamedTemporaryFile as tmpfile
|
|
1661
1693
|
except ImportError: # Python 2.7.16-
|
|
1662
|
-
from
|
|
1663
|
-
t =
|
|
1664
|
-
t =
|
|
1694
|
+
from _os import tmpfile # PYCHOK from
|
|
1695
|
+
t = _os.path.basename(self.pgm)
|
|
1696
|
+
t = _os.path.splitext(t)[0]
|
|
1665
1697
|
f = tmpfile(mode='w+b', prefix=t or 'egm')
|
|
1666
|
-
f.seek(0,
|
|
1698
|
+
f.seek(0, _os.SEEK_SET) # force overwrite
|
|
1667
1699
|
return f
|
|
1668
1700
|
|
|
1669
1701
|
@Property_RO
|
|
@@ -1703,7 +1735,7 @@ def egmGeoidHeights(GeoidHeights_dat):
|
|
|
1703
1735
|
dat = _BytesIO(dat)
|
|
1704
1736
|
|
|
1705
1737
|
try:
|
|
1706
|
-
dat.seek(0,
|
|
1738
|
+
dat.seek(0, _os.SEEK_SET) # reset
|
|
1707
1739
|
except AttributeError as x:
|
|
1708
1740
|
raise GeoidError(GeoidHeights_dat=type(dat), cause=x)
|
|
1709
1741
|
|
|
@@ -1711,11 +1743,26 @@ def egmGeoidHeights(GeoidHeights_dat):
|
|
|
1711
1743
|
t = t.strip()
|
|
1712
1744
|
if t and not t.startswith(_bHASH_):
|
|
1713
1745
|
lat, lon, egm84, egm96, egm2008 = map(float, t.split())
|
|
1714
|
-
|
|
1715
|
-
lon -= _360_0
|
|
1746
|
+
lon = _lonE2lon(lon) # Eastern to earth lon
|
|
1716
1747
|
yield GeoidHeight5Tuple(lat, lon, egm84, egm96, egm2008)
|
|
1717
1748
|
|
|
1718
1749
|
|
|
1750
|
+
def _lonE2lon(lon):
|
|
1751
|
+
'''(INTERNAL) East to earth longitude.
|
|
1752
|
+
'''
|
|
1753
|
+
while lon > _180_0:
|
|
1754
|
+
lon -= _360_0
|
|
1755
|
+
return lon
|
|
1756
|
+
|
|
1757
|
+
|
|
1758
|
+
def _lon2lonE(lon):
|
|
1759
|
+
'''(INTERNAL) Earth to East longitude.
|
|
1760
|
+
'''
|
|
1761
|
+
while lon < 0:
|
|
1762
|
+
lon += _360_0
|
|
1763
|
+
return lon
|
|
1764
|
+
|
|
1765
|
+
|
|
1719
1766
|
__all__ += _ALL_DOCS(_GeoidBase)
|
|
1720
1767
|
|
|
1721
1768
|
if __name__ == _DMAIN_: # MCCABE 14
|
pygeodesy/heights.py
CHANGED
|
@@ -59,7 +59,7 @@ C{>>> h1, h2, ... = hinterpolator.height_(lat1, lon1, lat2, lon2, ...)}
|
|
|
59
59
|
L{HeightSmoothBiSpline} require package U{scipy<https://SciPy.org>}.
|
|
60
60
|
Classes L{HeightIDWkarney} and L{HeightIDWdistanceTo} -if used with
|
|
61
61
|
L{ellipsoidalKarney.LatLon} points- require I{Karney}'s U{geographiclib
|
|
62
|
-
<https://PyPI.org/project/geographiclib>} to be installed.
|
|
62
|
+
<https://PyPI.org/project/geographiclib>} package to be installed.
|
|
63
63
|
|
|
64
64
|
@note: Errors from C{scipy} are raised as L{SciPyError}s. Warnings issued
|
|
65
65
|
by C{scipy} can be thrown as L{SciPyWarning} exceptions, provided
|
|
@@ -92,7 +92,7 @@ from pygeodesy.units import _isDegrees, Float_, Int_
|
|
|
92
92
|
# from math import radians # from .points
|
|
93
93
|
|
|
94
94
|
__all__ = _ALL_LAZY.heights
|
|
95
|
-
__version__ = '
|
|
95
|
+
__version__ = '26.02.02'
|
|
96
96
|
|
|
97
97
|
_error_ = 'error'
|
|
98
98
|
_formy = _MODS.into(formy=__name__)
|
|
@@ -160,7 +160,7 @@ def _orderedup(ts, lo=EPS, hi=PI2-EPS):
|
|
|
160
160
|
return sorted(set(max(lo, min(hi, t)) for t in ts)) # list
|
|
161
161
|
|
|
162
162
|
|
|
163
|
-
def _xyhs(wrap=False, _lat=_90_0, _lon=_180_0, **name_lls):
|
|
163
|
+
def _xyhs(wrap=False, _lat=_90_0, _lon=_180_0, height=True, **name_lls):
|
|
164
164
|
# map (lat, lon, h) to (x, y, h) in radians, offset
|
|
165
165
|
# x as 0 <= lon <= PI2 and y as 0 <= lat <= PI
|
|
166
166
|
name, lls = _xkwds_item2(name_lls)
|
|
@@ -168,8 +168,9 @@ def _xyhs(wrap=False, _lat=_90_0, _lon=_180_0, **name_lls):
|
|
|
168
168
|
try:
|
|
169
169
|
for i, ll in enumerate(lls):
|
|
170
170
|
y, x = _w(ll.lat, ll.lon)
|
|
171
|
-
|
|
172
|
-
|
|
171
|
+
h = ll.height if height else 0
|
|
172
|
+
yield (max(_0_0, _r(x + _lon)),
|
|
173
|
+
max(_0_0, _r(y + _lat)), h)
|
|
173
174
|
except Exception as x:
|
|
174
175
|
i = Fmt.INDEX(name, i)
|
|
175
176
|
raise HeightError(i, ll, cause=x)
|
|
@@ -266,9 +267,9 @@ class _HeightBase(_HeightNamed): # in .geoids
|
|
|
266
267
|
# convert lli C{LatLon}s to tuples or C{NumPy} arrays of
|
|
267
268
|
# C{SciPy} sphericals and determine the return type
|
|
268
269
|
atype = self.numpy.array
|
|
269
|
-
|
|
270
|
+
kwds = _xkwds(wrap, wrap=self._wrap, height=False)
|
|
270
271
|
_as, llis = _as_llis2(llis)
|
|
271
|
-
xis, yis, _ = zip(*_xyhs(llis=llis, **
|
|
272
|
+
xis, yis, _ = zip(*_xyhs(llis=llis, **kwds)) # PYCHOK yield
|
|
272
273
|
return _as, atype(xis), atype(yis), llis
|
|
273
274
|
|
|
274
275
|
def _ev(self, *args): # PYCHOK no cover
|
pygeodesy/internals.py
CHANGED
|
@@ -6,8 +6,8 @@ u'''Mostly INTERNAL functions, except L{machine}, L{print_} and L{printf}.
|
|
|
6
6
|
# from pygeodesy.basics import isiterablen, ubstr # _MODS
|
|
7
7
|
# from pygeodesy.errors import _AttributeError, _error_init, _ImmutableError, _UnexpectedError, _xError2 # _MODS
|
|
8
8
|
from pygeodesy.interns import _BAR_, _COLON_, _DASH_, _DMAIN_, _DOT_, _ELLIPSIS_, _NL_, NN, \
|
|
9
|
-
_pygeodesy_, _PyPy__, _python_, _QUOTE1_, _QUOTE2_,
|
|
10
|
-
_SPACE_, _UNDER_
|
|
9
|
+
_NLATvar_, _pygeodesy_, _PyPy__, _python_, _QUOTE1_, _QUOTE2_, \
|
|
10
|
+
_s_, _sys, _SPACE_, _UNDER_
|
|
11
11
|
from pygeodesy.interns import _COMMA_, _Python_ # PYCHOK used!
|
|
12
12
|
# from pygeodesy.streprs import anstr, pairs, unstr # _MODS
|
|
13
13
|
|
|
@@ -459,6 +459,13 @@ def _popen2(cmd, stdin=None): # in .mgrs, .solveBase, .testMgrs
|
|
|
459
459
|
return _MODS.basics.ub2str(r).strip(), p.returncode
|
|
460
460
|
|
|
461
461
|
|
|
462
|
+
def _pregistry(registry):
|
|
463
|
+
'''(INTERNAL) Print all items of a C{registry}.
|
|
464
|
+
'''
|
|
465
|
+
t = [NN] + registry.toRepr(all=True, asorted=True).split(_NL_)
|
|
466
|
+
printf(_NLATvar_.join(i.strip(_COMMA_) for i in t))
|
|
467
|
+
|
|
468
|
+
|
|
462
469
|
def print_(*args, **nl_nt_prec_prefix__end_file_flush_sep__kwds): # PYCHOK no cover
|
|
463
470
|
'''Python 3+ C{print}-like formatting and printing.
|
|
464
471
|
|
|
@@ -709,7 +716,7 @@ def _versions(sep=_SPACE_):
|
|
|
709
716
|
|
|
710
717
|
|
|
711
718
|
__all__ = tuple(map(typename, (machine, print_, printf, typename)))
|
|
712
|
-
__version__ = '
|
|
719
|
+
__version__ = '26.01.13'
|
|
713
720
|
|
|
714
721
|
if __name__ == _DMAIN_:
|
|
715
722
|
|
pygeodesy/lazily.py
CHANGED
|
@@ -30,8 +30,8 @@ and line number.
|
|
|
30
30
|
from pygeodesy import internals as _internals, interns as _interns, \
|
|
31
31
|
_isfrozen # DON'T _lazy_import2
|
|
32
32
|
# from pygeodesy.errors import _error_init, _ImmutableError, _xkwds_item2 # _ALL_MODS
|
|
33
|
-
from pygeodesy.internals import _caller3, _envPYGEODESY, _headof, printf,
|
|
34
|
-
|
|
33
|
+
from pygeodesy.internals import _caller3, _envPYGEODESY, _headof, printf, _Property_RO, \
|
|
34
|
+
_tailof, typename, _versions # _getenv, _PYGEODESY_ENV, \
|
|
35
35
|
# _MODS_Base, _MODS.sys_version_info2
|
|
36
36
|
from pygeodesy.interns import _attribute_, _by_, _COLONSPACE_, _COMMASPACE_, _DALL_, \
|
|
37
37
|
_DMAIN_, _doesn_t_exist_, _DOT_, _EQUALSPACED_, _from_, \
|
|
@@ -234,7 +234,8 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
|
|
|
234
234
|
'a_f2b', 'a_f_2b', 'b_f2a', 'b_f_2a',
|
|
235
235
|
'e2f', 'e22f',
|
|
236
236
|
'f2e2', 'f2e22', 'f2e32', 'f_2f', 'f2f_', 'f2f2', 'f2n', 'n2e2', 'n2f', 'n2f_'),
|
|
237
|
-
elliptic=_a('Elliptic', 'EllipticError', 'Elliptic3Tuple'
|
|
237
|
+
elliptic=_a('Elliperim', 'Elliptic', 'EllipticError', 'Elliptic3Tuple',
|
|
238
|
+
'elliperim', 'elliperim_'),
|
|
238
239
|
epsg=_a('Epsg', 'EPSGError'),
|
|
239
240
|
errors=_a('AuxError', 'ClipError', 'CrossError', 'GeodesicError', 'IntersectionError',
|
|
240
241
|
'NumPyError', 'LenError', 'LimitError', 'MGRSError',
|
|
@@ -250,10 +251,10 @@ _ALL_LAZY = _NamedEnum_RO(_name='_ALL_LAZY',
|
|
|
250
251
|
'fpolynomial', 'fpowers', 'fprod', 'frandoms', 'frange', 'freduce', 'fremainder',
|
|
251
252
|
'hypot', 'hypot_', 'hypot1', 'hypot2', 'hypot2_',
|
|
252
253
|
'norm2', 'norm_', 'sqrt0', 'sqrt3', 'sqrt_a', 'zcrt', 'zqrt'),
|
|
253
|
-
formy=_a('
|
|
254
|
+
formy=_a('Radical2Tuple',
|
|
254
255
|
'angle2chord', 'antipode', 'antipode_', 'bearing', 'bearing_',
|
|
255
256
|
'chord2angle', 'compassAngle', 'cosineLaw', 'cosineLaw_',
|
|
256
|
-
'
|
|
257
|
+
'equirectangular', 'equirectangular4', 'euclidean', 'euclidean_',
|
|
257
258
|
'excessAbc_', 'excessCagnoli_', 'excessGirard_', 'excessLHuilier_',
|
|
258
259
|
'excessKarney', 'excessKarney_', 'excessQuad', 'excessQuad_',
|
|
259
260
|
'flatLocal', 'flatLocal_', 'flatPolar', 'flatPolar_',
|
|
@@ -517,10 +518,16 @@ class _ALL_MODS(_internals._MODS_Base):
|
|
|
517
518
|
if _headof(n) == _pygeodesy_:
|
|
518
519
|
yield n, m
|
|
519
520
|
|
|
521
|
+
@_Property_RO
|
|
522
|
+
def _triaxials_triaxial5(self):
|
|
523
|
+
'''(INTERNAL) Get module C{triaxial.triaxials}.
|
|
524
|
+
'''
|
|
525
|
+
return self.triaxials.triaxial5
|
|
526
|
+
|
|
520
527
|
_internals._MODS = _ALL_MODS = _ALL_MODS() # PYCHOK singleton
|
|
521
528
|
|
|
522
529
|
__all__ = _ALL_LAZY.lazily
|
|
523
|
-
__version__ = '
|
|
530
|
+
__version__ = '26.01.06'
|
|
524
531
|
|
|
525
532
|
|
|
526
533
|
def _ALL_OTHER(*objs):
|
pygeodesy/lcc.py
CHANGED
|
@@ -651,13 +651,9 @@ def toLcc(latlon, conic=Conics.WRF_Lb, height=None, Lcc=Lcc,
|
|
|
651
651
|
|
|
652
652
|
|
|
653
653
|
if __name__ == _DMAIN_:
|
|
654
|
-
|
|
655
|
-
from pygeodesy.
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
# __doc__ of this file, force all into registery
|
|
659
|
-
t = _NL_ + Conics.toRepr(all=True, asorted=True)
|
|
660
|
-
printf(_NLATvar_.join(t.split(_NL_)))
|
|
654
|
+
# __doc__ of this file, force all into registry
|
|
655
|
+
from pygeodesy.internals import _pregistry
|
|
656
|
+
_pregistry(Conics)
|
|
661
657
|
|
|
662
658
|
# **) MIT License
|
|
663
659
|
#
|
pygeodesy/named.py
CHANGED
|
@@ -35,7 +35,7 @@ from pygeodesy.streprs import attrs, Fmt, lrstrip, pairs, reprs, unstr
|
|
|
35
35
|
# from pygeodesy.units import _toUnit # _MODS
|
|
36
36
|
|
|
37
37
|
__all__ = _ALL_LAZY.named
|
|
38
|
-
__version__ = '
|
|
38
|
+
__version__ = '26.01.14'
|
|
39
39
|
|
|
40
40
|
_COMMANL_ = _COMMA_ + _NL_
|
|
41
41
|
_COMMASPACEDOT_ = _COMMASPACE_ + _DOT_
|
|
@@ -658,18 +658,24 @@ class _NamedEnum(_NamedDict):
|
|
|
658
658
|
'''(INTERNAL) Check attribute name against given, registered name.
|
|
659
659
|
'''
|
|
660
660
|
pypy = _isPyPy()
|
|
661
|
-
_isa = isinstance
|
|
662
661
|
for n, v in kwds.items():
|
|
663
|
-
if
|
|
662
|
+
if isinstance(v, _LazyNamedEnumItem): # property
|
|
664
663
|
assert (n == v.name) if pypy else (n is v.name)
|
|
665
664
|
# assert not hasattr(self.__class__, n)
|
|
666
665
|
setattr(self.__class__, n, v)
|
|
667
|
-
elif
|
|
666
|
+
elif isinstance(v, self._item_Classes): # PYCHOK no cover
|
|
668
667
|
assert self[n] is v and getattr(self, n) \
|
|
669
668
|
and self.find(v) == n
|
|
670
669
|
else:
|
|
671
670
|
raise _TypeError(v, name=n)
|
|
672
671
|
|
|
672
|
+
def _asserts(self): # in .triaxials.triaxial3
|
|
673
|
+
'''(INTERNAL) Yield all asserted items.
|
|
674
|
+
'''
|
|
675
|
+
for n, p in tuple(type(self).__dict__.items()):
|
|
676
|
+
if isinstance(p, _LazyNamedEnumItem):
|
|
677
|
+
yield n, p
|
|
678
|
+
|
|
673
679
|
def find(self, item, dflt=None, all=False):
|
|
674
680
|
'''Find a registered item.
|
|
675
681
|
|
|
@@ -707,10 +713,8 @@ class _NamedEnum(_NamedDict):
|
|
|
707
713
|
case-insensitive} order (C{bool}).
|
|
708
714
|
'''
|
|
709
715
|
if all: # instantiate any remaining L{_LazyNamedEnumItem}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
if _isa(p, _LazyNamedEnumItem):
|
|
713
|
-
_ = getattr(self, n)
|
|
716
|
+
for n, _ in self._asserts():
|
|
717
|
+
_ = getattr(self, n)
|
|
714
718
|
return itemsorted(self) if asorted else ADict.items(self)
|
|
715
719
|
|
|
716
720
|
def keys(self, **all_asorted):
|
|
@@ -857,7 +861,7 @@ def _lazyNamedEnumItem(name, *args, **kwds):
|
|
|
857
861
|
|
|
858
862
|
|
|
859
863
|
class _NamedEnumItem(_NamedBase):
|
|
860
|
-
'''(INTERNAL) Base class for items in a C{_NamedEnum}
|
|
864
|
+
'''(INTERNAL) Base class for items in a C{_NamedEnum} registry.
|
|
861
865
|
'''
|
|
862
866
|
_enum = None
|
|
863
867
|
|
pygeodesy/trf.py
CHANGED
|
@@ -1754,7 +1754,7 @@ if __name__ == _DMAIN_:
|
|
|
1754
1754
|
t = '%d,%3d,%3d' % t
|
|
1755
1755
|
printf('# %s = %s = %s %s', f, e, t, x)
|
|
1756
1756
|
|
|
1757
|
-
# __doc__ of this file, force all into
|
|
1757
|
+
# __doc__ of this file, force all into registry
|
|
1758
1758
|
def _RFs():
|
|
1759
1759
|
yield NN
|
|
1760
1760
|
for t in RefFrames.toRepr(all=True).split(_NL_):
|