Skip to content

Commit cdfd0ae

Browse files
authored
A rotated NaN is still a NaN (#2901)
* fix: Rotated NaN is still a NaN Fix rotations outside of spice so they maintan FILL_VAL during rotation Before this we were introducing nearly but not quite NaN/FILL_VAL meaning very bad field data. * QA fix
1 parent 561aa28 commit cdfd0ae

2 files changed

Lines changed: 30 additions & 0 deletions

File tree

imap_processing/spice/geometry.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
import spiceypy
1919
from numpy.typing import NDArray
2020

21+
from imap_processing.mag import constants
22+
2123
logger = logging.getLogger(__name__)
2224

2325

@@ -317,6 +319,14 @@ def frame_transform(
317319
# Multiple et/positions : (n, 3, 3),(n, 3, 1) -> (n, 3, 1)
318320
result = np.squeeze(rotate @ position[..., np.newaxis])
319321

322+
# For every FILLVAL in the input position, ensure the output is also NaN or FILLVAL
323+
if np.isnan(position).any() or (position == constants.FILLVAL).any():
324+
result = np.where(
325+
np.isnan(position) | (position == constants.FILLVAL),
326+
constants.FILLVAL,
327+
result,
328+
)
329+
320330
return result
321331

322332

imap_processing/tests/spice/test_geometry.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import pytest
77
import spiceypy
88

9+
from imap_processing.mag import constants
910
from imap_processing.spice.geometry import (
1011
SpiceBody,
1112
SpiceFrame,
@@ -159,6 +160,19 @@ def test_get_spacecraft_to_instrument_spin_phase_offset(
159160
SpiceFrame.IMAP_SPACECRAFT,
160161
SpiceFrame.IMAP_DPS,
161162
),
163+
# single et, single NaN/FILL_VAL vector
164+
(
165+
["2025-04-30T12:00:00.000"],
166+
np.array(
167+
[
168+
[0, 0, 0],
169+
[constants.FILLVAL, constants.FILLVAL, constants.FILLVAL],
170+
[np.nan, np.nan, np.nan],
171+
]
172+
),
173+
SpiceFrame.IMAP_SPACECRAFT,
174+
SpiceFrame.IMAP_DPS,
175+
),
162176
],
163177
)
164178
def test_frame_transform(et_strings, position, from_frame, to_frame, furnish_kernels):
@@ -203,6 +217,12 @@ def test_frame_transform(et_strings, position, from_frame, to_frame, furnish_ker
203217
spice_result = spiceypy.mxv(rotation_matrix, spice_position)
204218
np.testing.assert_allclose(test_result, spice_result, atol=1e-12)
205219

220+
# Ensure that NaN/FILL_VAL inputs are preserved exactly as FILL_VAL outputs
221+
# and not just really close to but not quite FILL_VAL
222+
for input_vec, output_vec in zip(position, result, strict=False):
223+
if np.isnan(input_vec).all() or (input_vec == constants.FILLVAL).all():
224+
assert (output_vec == constants.FILLVAL).all()
225+
206226

207227
@pytest.mark.parametrize(
208228
"spice_frame",

0 commit comments

Comments
 (0)