[Git][debian-gis-team/pymap3d][upstream] New upstream version 2.7.3

Antonio Valentino (@antonio.valentino) gitlab at salsa.debian.org
Sat Nov 27 12:23:26 GMT 2021



Antonio Valentino pushed to branch upstream at Debian GIS Project / pymap3d


Commits:
51b4fedb by Antonio Valentino at 2021-11-27T12:13:52+00:00
New upstream version 2.7.3
- - - - -


9 changed files:

- .github/workflows/ci.yml
- README.md
- pyproject.toml
- setup.cfg
- src/pymap3d/aer.py
- src/pymap3d/ecef.py
- src/pymap3d/rsphere.py
- src/pymap3d/tests/test_geodetic.py
- src/pymap3d/utils.py


Changes:

=====================================
.github/workflows/ci.yml
=====================================
@@ -7,7 +7,7 @@ on:
     - .github/workflows/ci.yml
     pull-request:
     - "**.py"
-    - .github/workflows/ci_stdlib_only.yml
+    - .github/workflows/ci.yml
 
 jobs:
 


=====================================
README.md
=====================================
@@ -76,6 +76,9 @@ where tuple `lla` is comprised of scalar or N-D arrays `(lat,lon,alt)`.
 
 Example scripts are in the [examples](./Examples) directory.
 
+Native Python float is typically [64 bit](https://docs.python.org/3/library/stdtypes.html#typesnumeric).
+Numpy can select real precision bits: 32, 64, 128, etc.
+
 ### Functions
 
 Popular mapping toolbox functions ported to Python include the


=====================================
pyproject.toml
=====================================
@@ -1,6 +1,6 @@
 [project]
 name = "pymap3d"
-version = "2.6.1"
+version = "2.7.2"
 description = "pure Python (no prereqs) coordinate conversions, following convention of several popular Matlab routines."
 readme = "README.md"
 requires-python = ">=3.7"


=====================================
setup.cfg
=====================================
@@ -1,6 +1,6 @@
 [metadata]
 name = pymap3d
-version = 2.7.2
+version = 2.7.3
 author = Michael Hirsch, Ph.D.
 author_email = scivision at users.noreply.github.com
 description = pure Python (no prereqs) coordinate conversions, following convention of several popular Matlab routines.


=====================================
src/pymap3d/aer.py
=====================================
@@ -11,7 +11,7 @@ from .ellipsoid import Ellipsoid
 try:
     from .eci import eci2ecef, ecef2eci
 except ImportError:
-    eci2ecef = ecef2eci = None  # type: ignore
+    pass
 
 if typing.TYPE_CHECKING:
     from numpy import ndarray
@@ -212,10 +212,11 @@ def eci2aer(
     srange : float
          slant range [meters]
     """
-    if eci2ecef is None:
-        raise ImportError("pip install numpy")
 
-    xecef, yecef, zecef = eci2ecef(x, y, z, t, use_astropy=use_astropy)
+    try:
+        xecef, yecef, zecef = eci2ecef(x, y, z, t, use_astropy=use_astropy)
+    except NameError:
+        raise ImportError("pip install numpy")
 
     return ecef2aer(xecef, yecef, zecef, lat0, lon0, h0, deg=deg)
 
@@ -271,12 +272,13 @@ def aer2eci(
     z : float
         ECEF z coordinate (meters)
     """
-    if ecef2eci is None:
-        raise ImportError("pip install numpy")
 
     x, y, z = aer2ecef(az, el, srange, lat0, lon0, h0, ell, deg=deg)
 
-    return ecef2eci(x, y, z, t, use_astropy=use_astropy)
+    try:
+        return ecef2eci(x, y, z, t, use_astropy=use_astropy)
+    except NameError:
+        raise ImportError("pip install numpy")
 
 
 def aer2ecef(


=====================================
src/pymap3d/ecef.py
=====================================
@@ -3,7 +3,20 @@ from __future__ import annotations
 import typing
 
 try:
-    from numpy import radians, sin, cos, tan, arctan as atan, hypot, degrees, arctan2 as atan2, sqrt
+    from numpy import (
+        radians,
+        sin,
+        cos,
+        tan,
+        arctan as atan,
+        hypot,
+        degrees,
+        arctan2 as atan2,
+        sqrt,
+        finfo,
+        where,
+    )
+    from .eci import eci2ecef, ecef2eci
 except ImportError:
     from math import radians, sin, cos, tan, atan, hypot, degrees, atan2, sqrt  # type: ignore
 
@@ -13,11 +26,6 @@ from datetime import datetime
 from .ellipsoid import Ellipsoid
 from .utils import sanitize
 
-try:
-    from .eci import eci2ecef, ecef2eci
-except ImportError:
-    eci2ecef = ecef2eci = None  # type: ignore
-
 if typing.TYPE_CHECKING:
     from numpy import ndarray
 
@@ -80,8 +88,7 @@ def geodetic2ecef(
     N = ell.semimajor_axis ** 2 / sqrt(
         ell.semimajor_axis ** 2 * cos(lat) ** 2 + ell.semiminor_axis ** 2 * sin(lat) ** 2
     )
-    # Compute cartesian (geocentric) coordinates given  (curvilinear) geodetic
-    # coordinates.
+    # Compute cartesian (geocentric) coordinates given (curvilinear) geodetic coordinates.
     x = (N + alt) * cos(lat) * cos(lon)
     y = (N + alt) * cos(lat) * sin(lon)
     z = (N * (ell.semiminor_axis / ell.semimajor_axis) ** 2 + alt) * sin(lat)
@@ -150,18 +157,36 @@ def ecef2geodetic(
             Beta = -pi / 2
 
     # eqn. 13
-    eps = ((ell.semiminor_axis * u - ell.semimajor_axis * huE + E ** 2) * sin(Beta)) / (
+    dBeta = ((ell.semiminor_axis * u - ell.semimajor_axis * huE + E ** 2) * sin(Beta)) / (
         ell.semimajor_axis * huE * 1 / cos(Beta) - E ** 2 * cos(Beta)
     )
 
-    Beta += eps
+    Beta += dBeta
+
+    # eqn. 4c
     # %% final output
     lat = atan(ell.semimajor_axis / ell.semiminor_axis * tan(Beta))
 
+    try:
+        # patch latitude for float32 precision loss
+        lim_pi2 = pi / 2 - finfo(dBeta.dtype).eps
+        lat = where(Beta >= lim_pi2, pi / 2, lat)
+        lat = where(Beta <= -lim_pi2, -pi / 2, lat)
+    except NameError:
+        pass
+
     lon = atan2(y, x)
 
     # eqn. 7
-    alt = hypot(z - ell.semiminor_axis * sin(Beta), Q - ell.semimajor_axis * cos(Beta))
+    cosBeta = cos(Beta)
+    try:
+        # patch altitude for float32 precision loss
+        cosBeta = where(Beta >= lim_pi2, 0, cosBeta)
+        cosBeta = where(Beta <= -lim_pi2, 0, cosBeta)
+    except NameError:
+        pass
+
+    alt = hypot(z - ell.semiminor_axis * sin(Beta), Q - ell.semimajor_axis * cosBeta)
 
     # inside ellipsoid?
     inside = (
@@ -395,10 +420,11 @@ def eci2geodetic(
 
     eci2geodetic() a.k.a. eci2lla()
     """
-    if eci2ecef is None:
-        raise ImportError("pip install numpy")
 
-    xecef, yecef, zecef = eci2ecef(x, y, z, t, use_astropy=use_astropy)
+    try:
+        xecef, yecef, zecef = eci2ecef(x, y, z, t, use_astropy=use_astropy)
+    except NameError:
+        raise ImportError("pip install numpy")
 
     return ecef2geodetic(xecef, yecef, zecef, ell, deg)
 
@@ -446,12 +472,13 @@ def geodetic2eci(
 
     geodetic2eci() a.k.a lla2eci()
     """
-    if ecef2eci is None:
-        raise ImportError("pip install numpy")
 
     x, y, z = geodetic2ecef(lat, lon, alt, ell, deg)
 
-    return ecef2eci(x, y, z, t, use_astropy=use_astropy)
+    try:
+        return ecef2eci(x, y, z, t, use_astropy=use_astropy)
+    except NameError:
+        raise ImportError("pip install numpy")
 
 
 def enu2ecef(


=====================================
src/pymap3d/rsphere.py
=====================================
@@ -8,8 +8,6 @@ try:
 except ImportError:
     from math import radians, sin, cos, log, sqrt, degrees  # type: ignore
 
-    asarray = None  # type: ignore
-
 from .ellipsoid import Ellipsoid
 from . import rcurve
 from .vincenty import vdist
@@ -123,8 +121,11 @@ def euler(
     """
     if not deg:
         lat1, lon1, lat2, lon2 = degrees(lat1), degrees(lon1), degrees(lat2), degrees(lon2)
-    if asarray is not None:
+
+    try:
         lat1, lat2 = asarray(lat1), asarray(lat2)
+    except NameError:
+        pass
 
     latmid = lat1 + (lat2 - lat1) / 2  # compute the midpoint
 


=====================================
src/pymap3d/tests/test_geodetic.py
=====================================
@@ -13,6 +13,28 @@ ELL = pm.Ellipsoid()
 A = ELL.semimajor_axis
 B = ELL.semiminor_axis
 
+xyzlla = [
+    ((A - 1, 0, 0), (0, 0, -1)),
+    ((0, A - 1, 0), (0, 90, -1)),
+    ((0, 0, B - 1), (90, 0, -1)),
+    ((0, 0, B - 1), (89.999999, 0, -1)),
+    ((0, 0, B - 1), (89.99999, 0, -1)),
+    ((0, 0, -B + 1), (-90, 0, -1)),
+    ((0, 0, -B + 1), (-89.999999, 0, -1)),
+    ((0, 0, -B + 1), (-89.99999, 0, -1)),
+    ((-A + 1, 0, 0), (0, 180, -1)),
+]
+
+llaxyz = [
+    ((0, 0, -1), (A - 1, 0, 0)),
+    ((0, 90, -1), (0, A - 1, 0)),
+    ((0, -90, -1), (0, -A + 1, 0)),
+    ((90, 0, -1), (0, 0, B - 1)),
+    ((90, 15, -1), (0, 0, B - 1)),
+    ((-90, 0, -1), (0, 0, -B + 1)),
+]
+
+
 atol_dist = 1e-6  # 1 micrometer
 
 
@@ -94,7 +116,7 @@ def test_xarray():
     xyz = pm.geodetic2ecef(*xr_lla)
 
     assert xyz == approx(xyz0)
-    # %%
+
     xr_xyz = xarray.DataArray(list(xyz0))
 
     lla = pm.ecef2geodetic(*xr_xyz)
@@ -136,31 +158,12 @@ def test_ecef():
     assert pm.ecef2geodetic((A - 1) / sqrt(2), (A - 1) / sqrt(2), 0) == approx([0, 45, -1])
 
 
- at pytest.mark.parametrize(
-    "lla, xyz",
-    [
-        ((0, 0, -1), (A - 1, 0, 0)),
-        ((0, 90, -1), (0, A - 1, 0)),
-        ((0, -90, -1), (0, -A + 1, 0)),
-        ((90, 0, -1), (0, 0, B - 1)),
-        ((90, 15, -1), (0, 0, B - 1)),
-        ((-90, 0, -1), (0, 0, -B + 1)),
-    ],
-)
+ at pytest.mark.parametrize("lla, xyz", llaxyz)
 def test_geodetic2ecef(lla, xyz):
     assert pm.geodetic2ecef(*lla) == approx(xyz, abs=atol_dist)
 
 
- at pytest.mark.parametrize(
-    "xyz, lla",
-    [
-        ((A - 1, 0, 0), (0, 0, -1)),
-        ((0, A - 1, 0), (0, 90, -1)),
-        ((0, 0, B - 1), (90, 0, -1)),
-        ((0, 0, -B + 1), (-90, 0, -1)),
-        ((-A + 1, 0, 0), (0, 180, -1)),
-    ],
-)
+ at pytest.mark.parametrize("xyz, lla", xyzlla)
 def test_ecef2geodetic(xyz, lla):
     lat, lon, alt = pm.ecef2geodetic(*xyz)
     assert lat == approx(lla[0])
@@ -221,3 +224,37 @@ def test_somenan():
 
     lat, lon, alt = pm.ecef2geodetic(xyz[:, 0], xyz[:, 1], xyz[:, 2])
     assert (lat[0], lon[0], alt[0]) == approx(lla0)
+
+
+ at pytest.mark.parametrize("xyz, lla", xyzlla)
+def test_numpy_ecef2geodetic(xyz, lla):
+    np = pytest.importorskip("numpy")
+    lat, lon, alt = pm.ecef2geodetic(
+        *np.array(
+            [
+                [xyz],
+            ],
+            dtype=np.float32,
+        ).T
+    )
+    assert lat[0] == approx(lla[0])
+    assert lon[0] == approx(lla[1])
+    assert alt[0] == approx(lla[2])
+
+
+ at pytest.mark.parametrize("lla, xyz", llaxyz)
+def test_numpy_geodetic2ecef(lla, xyz):
+    np = pytest.importorskip("numpy")
+    x, y, z = pm.geodetic2ecef(
+        *np.array(
+            [
+                [lla],
+            ],
+            dtype=np.float32,
+        ).T
+    )
+
+    atol_dist = 1  # meters
+    assert x[0] == approx(xyz[0], abs=atol_dist)
+    assert y[0] == approx(xyz[1], abs=atol_dist)
+    assert z[0] == approx(xyz[2], abs=atol_dist)


=====================================
src/pymap3d/utils.py
=====================================
@@ -4,15 +4,14 @@ all assume radians"""
 
 from __future__ import annotations
 import typing
+from math import pi
 
 from .ellipsoid import Ellipsoid
 
 try:
-    from numpy import hypot, cos, sin, arctan2 as atan2, radians, pi, asarray, sign
+    from numpy import hypot, cos, sin, arctan2 as atan2, radians, asarray, sign
 except ImportError:
-    from math import atan2, hypot, cos, sin, radians, pi  # type: ignore
-
-    asarray = None  # type: ignore
+    from math import atan2, hypot, cos, sin, radians  # type: ignore
 
     def sign(x: float) -> float:  # type: ignore
         """signum function"""
@@ -63,17 +62,22 @@ def sph2cart(az: ndarray, el: ndarray, r: ndarray) -> tuple[ndarray, ndarray, nd
 def sanitize(
     lat: float | ndarray, ell: typing.Optional[Ellipsoid], deg: bool
 ) -> tuple[float | ndarray, Ellipsoid]:
+
     if ell is None:
         ell = Ellipsoid()
-    if asarray is not None:
+
+    try:
         lat = asarray(lat)
+    except NameError:
+        pass
+
     if deg:
         lat = radians(lat)
 
-    if asarray is not None:
+    try:
         if (abs(lat) > pi / 2).any():  # type: ignore
             raise ValueError("-pi/2 <= latitude <= pi/2")
-    else:
+    except AttributeError:
         if abs(lat) > pi / 2:  # type: ignore
             raise ValueError("-pi/2 <= latitude <= pi/2")
 



View it on GitLab: https://salsa.debian.org/debian-gis-team/pymap3d/-/commit/51b4fedba9e1668bbbe5041fa8506d38472dfc1e

-- 
View it on GitLab: https://salsa.debian.org/debian-gis-team/pymap3d/-/commit/51b4fedba9e1668bbbe5041fa8506d38472dfc1e
You're receiving this email because of your account on salsa.debian.org.


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20211127/91e07981/attachment-0001.htm>


More information about the Pkg-grass-devel mailing list