Skip to content

Commit dde1b9c

Browse files
committed
bugfix: catch Numpy ArithmeticError
fixes #78
1 parent 162d5db commit dde1b9c

File tree

6 files changed

+39
-15
lines changed

6 files changed

+39
-15
lines changed

src/pymap3d/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
* Fortran: [Maptran3D](https://github.com/geospace-code/maptran3d)
3030
"""
3131

32-
__version__ = "2.10.0"
32+
__version__ = "3.0.0"
3333

3434
from .aer import aer2ecef, aer2geodetic, ecef2aer, geodetic2aer
3535
from .ecef import (
@@ -94,6 +94,10 @@
9494
]
9595

9696
try:
97+
import numpy as np
98+
99+
np.seterr(all="raise")
100+
97101
from .aer import aer2eci, eci2aer
98102
from .azelradec import azel2radec, radec2azel
99103
from .eci import ecef2eci, eci2ecef

src/pymap3d/ecef.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
from math import pi
1313

1414
from .ellipsoid import Ellipsoid
15-
from .mathfun import atan, atan2, cos, degrees, hypot, radians, sin, sqrt, tan
15+
from .mathfun import atan, atan2, cos, degrees, hypot, isclose, radians, sin, sqrt, tan
1616
from .utils import sanitize
1717

1818
__all__ = [
@@ -70,8 +70,8 @@ def geodetic2ecef(
7070
lon = radians(lon)
7171

7272
# radius of curvature of the prime vertical section
73-
N = ell.semimajor_axis**2 / sqrt(
74-
ell.semimajor_axis**2 * cos(lat) ** 2 + ell.semiminor_axis**2 * sin(lat) ** 2
73+
N = ell.semimajor_axis**2 / hypot(
74+
ell.semimajor_axis * cos(lat), ell.semiminor_axis * sin(lat)
7575
)
7676
# Compute cartesian (geocentric) coordinates given (curvilinear) geodetic coordinates.
7777
x = (N + alt) * cos(lat) * cos(lon)
@@ -133,7 +133,7 @@ def ecef2geodetic(
133133
E = sqrt(ell.semimajor_axis**2 - ell.semiminor_axis**2)
134134

135135
# eqn. 4a
136-
u = sqrt(0.5 * (r**2 - E**2) + 0.5 * sqrt((r**2 - E**2) ** 2 + 4 * E**2 * z**2))
136+
u = sqrt(0.5 * (r**2 - E**2) + 0.5 * hypot(r**2 - E**2, 2 * E * z))
137137

138138
Q = hypot(x, y)
139139

@@ -142,8 +142,10 @@ def ecef2geodetic(
142142
# eqn. 4b
143143
try:
144144
Beta = atan(huE / u * z / hypot(x, y))
145-
except ZeroDivisionError:
146-
if z >= 0:
145+
except ArithmeticError:
146+
if isclose(z, 0):
147+
Beta = 0
148+
elif z > 0:
147149
Beta = pi / 2
148150
else:
149151
Beta = -pi / 2

src/pymap3d/latitude.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ def geodetic2conformal(geodetic_lat, ell: Ellipsoid = None, deg: bool = True):
344344
# compute conformal latitudes with correction for points at +90
345345
try:
346346
conformal_lat = 2 * atan(sqrt((f4 / f3) * ((f1 / f2) ** e))) - (pi / 2)
347-
except ZeroDivisionError:
347+
except ArithmeticError:
348348
conformal_lat = pi / 2
349349

350350
return degrees(conformal_lat) if deg else conformal_lat

src/pymap3d/mathfun.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
exp,
1616
hypot,
1717
inf,
18+
isclose,
1819
isnan,
1920
log,
2021
power,
@@ -36,6 +37,7 @@
3637
exp,
3738
hypot,
3839
inf,
40+
isclose,
3941
isnan,
4042
log,
4143
radians,
@@ -48,7 +50,7 @@ def power(x, y): # type: ignore
4850
return pow(x, y)
4951

5052
def sign(x) -> float: # type: ignore
51-
"""signum function"""
53+
"""signum"""
5254
if x < 0:
5355
y = -1.0
5456
elif x > 0:
@@ -58,9 +60,12 @@ def sign(x) -> float: # type: ignore
5860

5961
return y
6062

61-
def cbrt(x) -> float: # type: ignore
62-
"""math.cbrt was added in Python 3.11"""
63-
return x ** (1 / 3)
63+
try:
64+
import math.cbrt as cbrt # type: ignore
65+
except ImportError:
66+
67+
def cbrt(x) -> float: # type: ignore
68+
return x ** (1 / 3)
6469

6570

6671
__all__ = [
@@ -75,6 +80,7 @@ def cbrt(x) -> float: # type: ignore
7580
"exp",
7681
"hypot",
7782
"inf",
83+
"isclose",
7884
"isnan",
7985
"log",
8086
"power",

src/pymap3d/tests/test_geodetic.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,21 @@
1414
B = ELL.semiminor_axis
1515

1616
xyzlla = [
17+
((A, 0, 0), (0, 0, 0)),
1718
((A - 1, 0, 0), (0, 0, -1)),
19+
((A + 1, 0, 0), (0, 0, 1)),
20+
((0.1 * A, 0, 0), (0, 0, -0.9 * A)),
21+
((0.001 * A, 0, 0), (0, 0, -0.999 * A)),
22+
((0, A, 0), (0, 90, 0)),
1823
((0, A - 1, 0), (0, 90, -1)),
24+
((0, A + 1, 0), (0, 90, 1)),
25+
((0, 0.1 * A, 0), (0, 90, -0.9 * A)),
26+
((0, 0.001 * A, 0), (0, 90, -0.999 * A)),
27+
((0, 0, B), (90, 0, 0)),
28+
((0, 0, B + 1), (90, 0, 1)),
1929
((0, 0, B - 1), (90, 0, -1)),
30+
((0, 0, 0.1 * B), (90, 0, -0.9 * B)),
31+
((0, 0, 0.001 * B), (90, 0, -0.999 * B)),
2032
((0, 0, B - 1), (89.999999, 0, -1)),
2133
((0, 0, B - 1), (89.99999, 0, -1)),
2234
((0, 0, -B + 1), (-90, 0, -1)),
@@ -179,7 +191,7 @@ def test_ecef2geodetic(xyz, lla):
179191
lat, lon, alt = pm.ecef2geodetic(*xyz)
180192
assert lat == approx(lla[0])
181193
assert lon == approx(lla[1])
182-
assert alt == approx(lla[2])
194+
assert alt == approx(lla[2], abs=1e-9)
183195

184196

185197
@pytest.mark.parametrize(

src/pymap3d/vincenty.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,10 +190,10 @@ def vdist(
190190
alpha[isnan(sinAlpha)] = 0
191191
alpha[(sinAlpha > 1) | (abs(sinAlpha - 1) < 1e-16)] = pi / 2
192192

193-
except (ZeroDivisionError, TypeError, ValueError):
193+
except (ArithmeticError, TypeError, ValueError):
194194
try:
195195
sinAlpha = cos(U1) * cos(U2) * sin(lamb) / sin(sigma)
196-
except ZeroDivisionError:
196+
except ArithmeticError:
197197
sinAlpha = 0.0
198198

199199
if isnan(sinAlpha):

0 commit comments

Comments
 (0)