geospace-code / pymap3d

pure-Python (Numpy optional) 3D coordinate conversions for geospace ecef enu eci
https://geospace-code.github.io/pymap3d
BSD 2-Clause "Simplified" License
391 stars 85 forks source link

[Bug]: Test failure or ARM architecture #87

Open avalentino opened 1 year ago

avalentino commented 1 year ago

What happened?

Recently e have updated the Debian package for pymap3d for v2.9.1 to v3.0 and we have started having some test failues on one of our ARM architectures

See the detailed log at: https://ci.debian.net/data/autopkgtest/testing/armel/p/pymap3d/34582756/log.gz

Relevant log output

============================= test session starts ==============================
platform linux -- Python 3.11.4, pytest-7.2.1, pluggy-1.0.0+repack
rootdir: /tmp/autopkgtest-lxc.5m0tpwuk/downtmp
plugins: astropy-header-0.2.2, mock-3.8.2, openfiles-0.5.0, arraydiff-0.5.0, cov-4.0.0, remotedata-0.4.0, astropy-0.10.0, doctestplus-0.12.1, filter-subpackage-0.1.2, hypothesis-6.67.1
collected 321 items

../build.4yE/src/src/pymap3d/tests/test_aer.py ..........                [  3%]
../build.4yE/src/src/pymap3d/tests/test_eci.py .....                     [  4%]
../build.4yE/src/src/pymap3d/tests/test_ellipsoid.py ................... [ 10%]
.................                                                        [ 15%]
../build.4yE/src/src/pymap3d/tests/test_enu.py .....                     [ 17%]
../build.4yE/src/src/pymap3d/tests/test_geodetic.py .................... [ 23%]
F....F....................F....F.................                        [ 38%]
../build.4yE/src/src/pymap3d/tests/test_latitude.py .................... [ 45%]
.........................                                                [ 52%]
../build.4yE/src/src/pymap3d/tests/test_look_spheroid.py .........       [ 55%]
../build.4yE/src/src/pymap3d/tests/test_ned.py ...                       [ 56%]
../build.4yE/src/src/pymap3d/tests/test_pyproj.py ..                     [ 57%]
../build.4yE/src/src/pymap3d/tests/test_rcurve.py .............          [ 61%]
../build.4yE/src/src/pymap3d/tests/test_rhumb.py ....................... [ 68%]
..........                                                               [ 71%]
../build.4yE/src/src/pymap3d/tests/test_rsphere.py ..........            [ 74%]
../build.4yE/src/src/pymap3d/tests/test_sidereal.py ....                 [ 76%]
../build.4yE/src/src/pymap3d/tests/test_sky.py ....                      [ 77%]
../build.4yE/src/src/pymap3d/tests/test_spherical.py ................... [ 83%]
.......................                                                  [ 90%]
../build.4yE/src/src/pymap3d/tests/test_time.py .....                    [ 91%]
../build.4yE/src/src/pymap3d/tests/test_vincenty.py .                    [ 92%]
../build.4yE/src/src/pymap3d/tests/test_vincenty_dist.py ............... [ 96%]
.                                                                        [ 97%]
../build.4yE/src/src/pymap3d/tests/test_vincenty_vreckon.py .........    [100%]

=================================== FAILURES ===================================
________________________ test_ecef2geodetic[xyz4-lla4] _________________________

xyz = (6378.137, 0, 0), lla = (0, 0, -6371758.863)

    @pytest.mark.parametrize("xyz, lla", xyzlla)
    def test_ecef2geodetic(xyz, lla):
        lat, lon, alt = pm.ecef2geodetic(*xyz)
>       assert lat == approx(lla[0])
E       assert nan == 0 ± 1.0e-12
E         comparison failed
E         Obtained: nan
E         Expected: 0 ± 1.0e-12

../build.4yE/src/src/pymap3d/tests/test_geodetic.py:192: AssertionError
________________________ test_ecef2geodetic[xyz9-lla9] _________________________

xyz = (0, 6378.137, 0), lla = (0, 90, -6371758.863)

    @pytest.mark.parametrize("xyz, lla", xyzlla)
    def test_ecef2geodetic(xyz, lla):
        lat, lon, alt = pm.ecef2geodetic(*xyz)
>       assert lat == approx(lla[0])
E       assert nan == 0 ± 1.0e-12
E         comparison failed
E         Obtained: nan
E         Expected: 0 ± 1.0e-12

../build.4yE/src/src/pymap3d/tests/test_geodetic.py:192: AssertionError
_____________________ test_numpy_ecef2geodetic[xyz4-lla4] ______________________

xyz = (6378.137, 0, 0), lla = (0, 0, -6371758.863)

    @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])
E       assert array([nan], dtype=float32) == 0 ± 1.0e-12
E         comparison failed
E         Obtained: [nan]
E         Expected: 0 ± 1.0e-12

../build.4yE/src/src/pymap3d/tests/test_geodetic.py:263: AssertionError
_____________________ test_numpy_ecef2geodetic[xyz9-lla9] ______________________

xyz = (0, 6378.137, 0), lla = (0, 90, -6371758.863)

    @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])
E       assert array([nan], dtype=float32) == 0 ± 1.0e-12
E         comparison failed
E         Obtained: [nan]
E         Expected: 0 ± 1.0e-12

../build.4yE/src/src/pymap3d/tests/test_geodetic.py:263: AssertionError
=============================== warnings summary ===============================
build.4yE/src/src/pymap3d/tests/test_pyproj.py::test_compare_geodetic
  /tmp/autopkgtest-lxc.5m0tpwuk/downtmp/build.4yE/src/src/pymap3d/tests/test_pyproj.py:31: FutureWarning: This function is deprecated. See: https://pyproj4.github.io/pyproj/stable/gotchas.html#upgrading-to-pyproj-2-from-pyproj-1
    assert pyproj.transform(lla, ecef, lla0[1], lla0[0], lla0[2]) == approx(xyz)

build.4yE/src/src/pymap3d/tests/test_pyproj.py::test_compare_geodetic
  /tmp/autopkgtest-lxc.5m0tpwuk/downtmp/build.4yE/src/src/pymap3d/tests/test_pyproj.py:32: FutureWarning: This function is deprecated. See: https://pyproj4.github.io/pyproj/stable/gotchas.html#upgrading-to-pyproj-2-from-pyproj-1
    assert pyproj.transform(ecef, lla, *xyz) == approx((lla0[1], lla0[0], lla0[2]))

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
=========================== short test summary info ============================
FAILED ../build.4yE/src/src/pymap3d/tests/test_geodetic.py::test_ecef2geodetic[xyz4-lla4]
FAILED ../build.4yE/src/src/pymap3d/tests/test_geodetic.py::test_ecef2geodetic[xyz9-lla9]
FAILED ../build.4yE/src/src/pymap3d/tests/test_geodetic.py::test_numpy_ecef2geodetic[xyz4-lla4]
FAILED ../build.4yE/src/src/pymap3d/tests/test_geodetic.py::test_numpy_ecef2geodetic[xyz9-lla9]
================== 4 failed, 317 passed, 2 warnings in 29.81s =================
avalentino commented 1 year ago

Looking at the code there is something that I cannot understand:

https://github.com/geospace-code/pymap3d/blob/81172e221a4c9884450a38ec8a7ee382198cb7e3/src/pymap3d/ecef.py#L145-L161

If Beta is set to +/- pi/2 then the computation of 1 / cos(Beta) will result in a nan.

Probably the expression can be re-written as follows to avoid this kind of issue:

    # eqn. 13
-    dBeta = ((ell.semiminor_axis * u - ell.semimajor_axis * huE + E**2) * sin(Beta)) / (
-        ell.semimajor_axis * huE * 1 / cos(Beta) - E**2 * cos(Beta)
+    dBeta = ((ell.semiminor_axis * u - ell.semimajor_axis * huE + E**2) * sin(Beta)) * cos(Beta) / (
+        ell.semimajor_axis * huE - E**2 * cos(Beta)**2
    )

By the way I think that the root cause of this issue is different

scivision commented 9 months ago

@avalentino I attempted a fix in f3a3a53.

avalentino commented 9 months ago

Dear @scivision sorry I'm no longer in the condition to be able to quickly check your changes on an ARM platform. I will be able to provide a feedback the next time I upload a new version of pymap3d in debian. Do you already have an idea about when we will have a new release?