Skip to content

Add optional Lagrange interpolation of quaternions to the ISD path - #727

Open
oleg-alexandrov wants to merge 2 commits into
DOI-USGS:mainfrom
oleg-alexandrov:lagrange_rotation_python
Open

Add optional Lagrange interpolation of quaternions to the ISD path#727
oleg-alexandrov wants to merge 2 commits into
DOI-USGS:mainfrom
oleg-alexandrov:lagrange_rotation_python

Conversation

@oleg-alexandrov

@oleg-alexandrov oleg-alexandrov commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Add optional Lagrange interpolation of quaternions to the ISD generation path

This is the ISD-side follow-up to #726, which added order-8 Lagrange interpolation of quaternions to ale::Orientations (the C++ runtime path that ISIS delegates to). This PR brings the same reconstruction to the Python ISD generation path, so an ISD can carry a Lagrange-consistent sensor orientation that matches ISIS and USGSCSM.

How to invoke

The new path is off by default and SLERP output is byte-for-byte unchanged. The primary interface is the rotation_interpolation prop, set to lagrange. For example:

ale.loads(cube_path, props={'rotation_interpolation': 'lagrange'})

I also added a matching --rotation_interpolation option to isd_generate so the path can be exercised from the command line for testing:

isd_generate --rotation_interpolation lagrange input.cub

I am treating that command-line option as provisional. It may need to be dropped once the approach is settled.

Question

Making Lagrange interpolation default would change every linescan ISD ALE emits, would require regenerating all golden ISDs, and would slightly shift downstream USGSCSM results (toward ISIS, but still a change). Should it eventually become the default? If so, I can do that in a follow-up with the golden ISD regeneration.

The USGSCSM side

It is not clear what to do on the USGSCSM side.

The linescan reader, UsgsAstroLsSensorModel getQuaternions, already does order-8 Lagrange over the uniform quaternion table and renormalizes, so a shorter or Lagrange-consistent table is already read correctly. I did not add an interpolation-order field to the ISD, because both ALE and USGSCSM default to order 8 and both clamp the window symmetrically when there are fewer nodes, so the two sides already agree without a new field.

Size reduction

This PR does not change the node count by itself. The existing reduction and ephem_sample_rate options control how many nodes are written. Combined with the Lagrange reconstruction here, a reduced node set can be read back accurately, which is the path to smaller ISDs. Keeping the two knobs separate makes each one reviewable on its own.

Tests

New pytest coverage is added. The Lagrange kernel reproduces a low-degree polynomial exactly. The reconstruction reproduces the input rotations at the node times. It is far more accurate than SLERP on a variable-rate rotation, and it is invariant to a sign flip of alternate input quaternions. All tests pass.

Changelog

A changelog entry is added under Unreleased.

Notes

Developed with Claude (AI) assistance. The code was reviewed. Comments and the API were adjusted as needed.

Licensing

  • I dedicate any and all copyright interest in this software to the public domain. I make this dedication for the benefit of the public at large and to the detriment of my heirs and successors. I intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.

oleg-alexandrov and others added 2 commits July 6, 2026 09:28
The linescan ISD formatter reinterpolates the sensor orientation onto a
uniform quaternion grid with 2-point SLERP, which misses curvature when the
rotation rate is not constant and does not match ISIS or USGSCSM. This adds an
order-8 Lagrange reconstruction as an opt-in alternative, a Python twin of the
ale::Orientations Lagrange path added in PR 726. It is off by default (SLERP is
unchanged) and selected with the rotation_interpolation prop or the
--rotation_interpolation lagrange option of isd_generate. The quaternions are
made sign-continuous and renormalized before interpolation.

Added pytest coverage for the interpolation kernel, node reproduction, accuracy
versus SLERP, sign-flip invariance, and formatter routing. A changelog entry is
added.

Developed with Claude (AI) assistance.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The rotation_interpolation prop is the primary interface. The isd_generate
command-line option is a provisional testing convenience, so keep the changelog
focused on the prop.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@oleg-alexandrov
oleg-alexandrov requested a review from Kelvinrr July 6, 2026 17:26
@Kelvinrr
Kelvinrr requested a review from acpaquette July 7, 2026 21:53
@acpaquette

Copy link
Copy Markdown
Collaborator

@oleg-alexandrov Initial thought is that it would be nice to see an A, B, and C comparison of the data between original ISIS, current ALE, and ALE using the lagrange interpolation. I understand if you don't have time for that

@oleg-alexandrov

Copy link
Copy Markdown
Collaborator Author

Yeah, kind of out of time. I must say that this is tricky enough that the originators of this issue, likely you, should do an eval. It is one heck of a change.

I would like your thoughts on the other PR with dead code. Sorry to sound like broken record. This has been a persistent annoyance ever since the time I worked with Jesse 5 years ago. Dead code that refuses to go and I keep on reading the wrong code any time I do ALE work. Not good for one's quality of life.

@acpaquette

Copy link
Copy Markdown
Collaborator

@oleg-alexandrov I'm not sure what dead code you are referring to. Could you link the PR/code you're talking about?

@oleg-alexandrov

Copy link
Copy Markdown
Collaborator Author

It is this one. #698

Sorry again for having this discussion in many places and likely counterproductive insistence.

I would like to ask however to consider that issue on its merits given your own rules. It seems that breaking change should have occured with version 1.0 in 2020 or with version 2.0 sometimes in 2024 or so. I am not sure we should wait more.

That has a conflict. I can fix.

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.

2 participants