Skip to content

task: Add more SPICE frames for MAG L2 processing and fix issue with SPICE epochs missing#2378

Merged
maxinelasp merged 10 commits intoIMAP-Science-Operations-Center:devfrom
ImperialCollegeLondon:task/l2-frames
Nov 7, 2025
Merged

task: Add more SPICE frames for MAG L2 processing and fix issue with SPICE epochs missing#2378
maxinelasp merged 10 commits intoIMAP-Science-Operations-Center:devfrom
ImperialCollegeLondon:task/l2-frames

Conversation

@mfacchinelli
Copy link
Copy Markdown
Collaborator

@mfacchinelli mfacchinelli commented Nov 4, 2025

Change Summary

Overview

This change:

  1. Adds transformation of MAG L2 data to 3 new frames (GSE, GSM, RTN)
  2. Fixes a few issues with processing MAG L2 data due to:
    a. DSRF transformation not being defined during periods of thruster firing (transformation matrix is now all NaNs)
    b. Truncates L2 data to the specified day at the beginning of L2 processing
    c. Truncation also crops epoch_et

Note

The current implementation will require a lot of memory for processing Burst mode in 128 cadence (as the data for 1 entire day will be held in memory for 5 different frames).

New Dependencies

N/A

New Files

N/A

Deleted Files

N/A

Updated Files

  • imap_mag_global_cdf_attrs.yaml
    • Adds definition for GSM reference frame
  • mag_l2.py:
    • Adds conversion to all supported reference frames
  • mag_l2_data.py:
    • Adds enum for GSM reference frame
    • Also crops epoch_et when truncating
  • geometry.py:
    • If SPICE tranformation fails becuase of SpiceNOFRAMECONNECT, i.e., no SPICE data is available for a specific timestamp (this happens every day between 10 and 10:30 AM for the despun reference frame, due to thruster firing), a NaN matrix is returned, instead of an error being thrown
  • test_mag_l2.py:
    • Modifies existing test to expect 5 datasets for each frame
    • Adds a test to make sure NaN matrices are supported
  • test_geometry.py:
    • Adds a test to make sure get_rotation_matrix returns NaN matrix when despun frame not defined for input et

Testing

Testing was added to cover all cases.

@mfacchinelli mfacchinelli changed the title task: Add more SPICE frames for MAG L2 processing and fix issues with SPICE epochs missing task: Add more SPICE frames for MAG L2 processing and fix issue with SPICE epochs missing Nov 4, 2025
@maxinelasp
Copy link
Copy Markdown
Contributor

Relates to: #2297, #2295

Copy link
Copy Markdown
Contributor

@tmplummer tmplummer left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know this is still just a draft, but I thought that I would leave some comments anyway.

Comment thread imap_processing/spice/geometry.py Outdated
): # numpydoc ignore=GL08
try:
return spiceypy.pxform(*arg, **kwargs)
except spiceypy.utils.exceptions.SpiceNOFRAMECONNECT:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation concerns me. I want this function to fail loudly by default rather than just logging an exception level message. I would be more comfortable with adding a keyword argument called something like allow_spice_noframeconnect that defaults to False.

try:
    return spiceypy.pxform(*arg, **kwargs)
except spiceypy.utils.exceptions.SpiceNOFRAMECONNECT as e:
    if not allow_spice_noframeconnect:
        raise(e)
    logger.debug(f"Returning NaN rotation matrix due to spiceypy error: {e}")
    return np.full((3, 3), np.nan)

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense, done!

Comment on lines +359 to +375
@pytest.mark.external_kernel
def test_get_rotation_matrix_no_transformation_defined_for_et(furnish_kernels):
"""Test error handling in get_rotation_matrix()."""
kernels = [
"naif0012.tls",
"imap_100.tf",
"imap_sclk_0000.tsc",
"imap_science_100.tf",
"sim_1yr_imap_attitude.bc",
"sim_1yr_imap_pointing_frame.bc",
"de440s.bsp",
]
with furnish_kernels(kernels):
# Midnight is not defined in pointing frame
et = spiceypy.utc2et("2029-01-01T00:00:00.000")
rotation = get_rotation_matrix(et, SpiceFrame.IMAP_MAG_O, SpiceFrame.IMAP_DPS)
assert np.isnan(rotation).all()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to also check that the vectorized form works:

# one hour after midnight should have coverage
ets = np.array([et, et + 3600])
rotations = get_rotation_matrix(ets, SpiceFrame.IMAP_MAG_O, SpiceFrame.IMAP_DPS)
assert rotations.shape == (2, 3, 3)
assert np.isnan(rotations[0]).all()
assert np.isfinite(rotations[1]).all()

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added this test, and a test for the default allow_spice_noframeconnect value, where we throw an error.

Comment thread imap_processing/mag/l2/mag_l2.py Outdated
try:
l2_data.rotate_frame(frame)
frames.append(l2_data.generate_dataset(attributes, day))
except Exception:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broad exceptions like this are generally bad and in this case all details about what caused the failure to rotate the data to the desired frame is lost.

Are there specific reasons you expect this to fail and can you handle those specific exceptions?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've removed this as this change addresses the failures we have seen in the past.

Btw, the logger.exception method does log the exception information automatically (including stacktrace), without having to pass the exception directly:
https://docs.python.org/3/library/logging.html#logging.Logger.exception

The same is true when passing exc_info to other logging methods, like I've done for the debug call.

@mfacchinelli
Copy link
Copy Markdown
Collaborator Author

I know this is still just a draft, but I thought that I would leave some comments anyway.

Thanks Tim, I've implemented the feedback. I'll get it tested in the dev environment with the files that have failed in the past.

@tmplummer
Copy link
Copy Markdown
Contributor

This all looks reasonable to me. @mfacchinelli, will you please convert this to a regular PR, as opposed to a Draft, and add @maxinelasp and @greglucas as additional reviewers?

@mfacchinelli mfacchinelli marked this pull request as ready for review November 5, 2025 17:13
@mfacchinelli
Copy link
Copy Markdown
Collaborator Author

This all looks reasonable to me. @mfacchinelli, will you please convert this to a regular PR, as opposed to a Draft, and add @maxinelasp and @greglucas as additional reviewers?

I can't add reviewers, but the tag should also work!

Copy link
Copy Markdown
Contributor

@maxinelasp maxinelasp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me! I am adding the SPICE kernels as required for L2 that I missed (ephemeris kernels). Let me know when you're done testing and ready to merge it. Thanks for the fix!

DSRF = SpiceFrame.IMAP_DPS
SRF = SpiceFrame.IMAP_SPACECRAFT
GSE = SpiceFrame.IMAP_GSE
GSM = SpiceFrame.IMAP_GSM
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to add GSM for the L1D processing as well?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, GSM is not used for L1d

@mfacchinelli
Copy link
Copy Markdown
Collaborator Author

mfacchinelli commented Nov 7, 2025

This looks good to me! I am adding the SPICE kernels as required for L2 that I missed (ephemeris kernels). Let me know when you're done testing and ready to merge it. Thanks for the fix!

Thanks @maxinelasp. I've tested it locally, and it generated all the expected L2 files. Mhairi had a look at them and she was happy.

For me this is ready to merge.

@maxinelasp maxinelasp merged commit 786936a into IMAP-Science-Operations-Center:dev Nov 7, 2025
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants