Skip to content

Commit 8e0c677

Browse files
authored
Fix vector to angles for small intensities (#565)
When the intensity is very small (<1e-10), the vector to angles calculation fails because of the masking that was used. It rounds these numbers to zero and returns always inc=90, dec=0. To handle this, use the arctangent instead of arcsine in the equations. This was, we can use arctan2 which is able to handle 0 in the denominator. Add tests to make sure this doesn't happen again. These small values appear in magnetic microscopy and we ran into this issue in Magali.
1 parent 57cdc55 commit 8e0c677

File tree

2 files changed

+19
-16
lines changed

2 files changed

+19
-16
lines changed

harmonica/_utils.py

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,6 @@ def magnetic_vec_to_angles(magnetic_e, magnetic_n, magnetic_u, degrees=True):
6868
Inclination is measured positive downward from the horizontal plane and
6969
declination is measured with respect to North and it is positive east.
7070
71-
7271
Parameters
7372
----------
7473
magnetic_e : float or array
@@ -119,7 +118,7 @@ def magnetic_vec_to_angles(magnetic_e, magnetic_n, magnetic_u, degrees=True):
119118
120119
.. math::
121120
122-
D = \arcsin \frac{B_e}{\sqrt{B_e^2 + B_n^2}}
121+
D = \arctan \frac{B_e}{B_n}
123122
124123
Examples
125124
--------
@@ -130,23 +129,14 @@ def magnetic_vec_to_angles(magnetic_e, magnetic_n, magnetic_u, degrees=True):
130129
# Compute the intensity as a norm
131130
intensity = np.sqrt(magnetic_e**2 + magnetic_n**2 + magnetic_u**2)
132131
# Compute the horizontal component of the magnetic vector
133-
horizontal_component = np.atleast_1d(np.sqrt(magnetic_e**2 + magnetic_n**2))
134-
# Mask the values equal to zero in the horizontal component
135-
horizontal_component = np.ma.masked_values(horizontal_component, 0.0)
136-
# Calculate the inclination and declination using the mask
137-
inclination = np.arctan(-magnetic_u / horizontal_component)
138-
declination = np.arcsin(magnetic_e / horizontal_component)
139-
# Fill the masked values
140-
inclination = inclination.filled(-np.sign(magnetic_u) * np.pi / 2)
141-
declination = declination.filled(0)
132+
horizontal_component = np.sqrt(magnetic_e**2 + magnetic_n**2)
133+
# Calculate the inclination and declination
134+
inclination = np.arctan2(-magnetic_u, horizontal_component)
135+
declination = np.arctan2(magnetic_e, magnetic_n)
142136
# Convert to degree if needed
143137
if degrees:
144138
inclination = np.degrees(inclination)
145139
declination = np.degrees(declination)
146-
# Cast to floats if all components are floats
147-
if intensity.ndim == 0:
148-
(inclination,) = inclination
149-
(declination,) = declination
150140
return intensity, inclination, declination
151141

152142

harmonica/tests/test_utils.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,22 @@
1717
[0, 0, -1], # Over -z axis
1818
[1, 0, 0], # Over east (y) axis
1919
[0, 1, 0], # Over north (x) axis
20+
[0, 0, -1e-13], # Over -z axis
21+
[1e-13, 0, 0], # Over east (y) axis
22+
[0, 1e-13, 0], # Over north (x) axis
2023
]
2124

22-
ANGLES = [[1, 45, 45], [1, -45, 45.0], [1, 45, -45], [1, 90, 0], [1, 0, 90], [1, 0, 0]]
25+
ANGLES = [
26+
[1, 45, 45],
27+
[1, -45, 45.0],
28+
[1, 45, -45],
29+
[1, 90, 0],
30+
[1, 0, 90],
31+
[1, 0, 0],
32+
[1e-13, 90, 0],
33+
[1e-13, 0, 90],
34+
[1e-13, 0, 0],
35+
]
2336

2437

2538
@pytest.mark.parametrize("angles, vector", [(a, v) for a, v in zip(ANGLES, VECTORS)])

0 commit comments

Comments
 (0)