Skip to content

Provide addendum-only TGO CaSSIS constants in the driver so isd_generate produces a complete ISD#732

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

Provide addendum-only TGO CaSSIS constants in the driver so isd_generate produces a complete ISD#732
oleg-alexandrov wants to merge 2 commits into
DOI-USGS:mainfrom
oleg-alexandrov:cassis_driver_addendum

Conversation

@oleg-alexandrov

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

Copy link
Copy Markdown
Collaborator

The TGO CaSSIS driver builds its ISD from the mission metakernel on the NaifSpice path, which is what isd_generate uses. Several CaSSIS instrument constants live only in the ISIS addendum kernel (tgoCassisAddendum), not in any NAIF instrument kernel, so on the NaifSpice path they were read as null or False and the ISD was incomplete or geometrically wrong. Following the Cassini driver precedent, the driver now returns these addendum-only values:

  • Focal length (874.9 mm). Without it the ISD is incomplete and no camera can be built.
  • The focal-plane to pixel transforms ITRANSS and ITRANSL.
  • The CaSSIS optical distortion model (the 36 OD_A coefficients).
  • The light-time flags LT_SURFACE_CORRECT, SWAP_OBSERVER_TARGET, and LIGHTTIME_CORRECTION set to LT+S. Without these the driver samples the target at the raw epoch rather than the surface light-time adjusted one, giving a constant camera-center offset of about 96 m from the ISIS camera.

With these, isd_generate produces a complete CSM camera whose geometry matches the ISIS camera.

Validation: the ale test suite passes, with a new test asserting the CaSSIS focal length on the NaifSpice path. The camera was also checked with the Ames Stereo Pipeline cam_test tool, comparing the ISIS camera from a spiceinit'd cube against the CSM camera from the isd_generate ISD. They agree to a camera center difference of 1.7e-9 m, a look direction difference of 3.7e-15, and a pixel difference of 0.0007 px median and 0.013 px max over the frame.

A reviewer can reproduce that with cam_test on the sample cube cas_cal_sc_20210725T202818-20210725T202822-16378-10-PAN-838849161-0-0__4_0.cub (observation MY36_016378_162_1, Jezero, 2021-07-25), which we can provide on request. It needs a USGSCSM build with CaSSIS distortion support, already merged in USGSCSM, and spiceinit to succeed on the cube. On recent CaSSIS observations spiceinit currently fails with "No instrument position available" because the shipped TGO SPK database omits the reconstructed spacecraft positions, tracked in DOI-USGS/ISIS3#6094.

This work was done with Claude, an AI assistant.

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.

The CaSSIS focal length, ITRANSS/ITRANSL, distortion model, and light-time
flags are defined only in the ISIS addendum kernel, so on the NaifSpice path
they were read as null or False and isd_generate produced an incomplete or
geometrically wrong ISD. Return them from the driver, following the Cassini
precedent. The resulting CSM camera matches the ISIS camera to a few
thousandths of a pixel.

Done with Claude, an AI assistant.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@Kelvinrr
Kelvinrr self-requested a review July 17, 2026 16:06

@acpaquette acpaquette left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

A few potential difference between the USGSCSM and ISIS TGO Cassis cameras that should be explored

instrument id
"""
id_lookup = {
'CaSSIS': 'TGO_CASSIS',

@acpaquette acpaquette Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I don't think this driver was fleshed out very well for use with USGSCSM when originally created. I think we want to expand the lookup table to handle:

      TGO_CASSIS                   -143400
      TGO_CASSIS_PAN               -143421
      TGO_CASSIS_RED               -143422
      TGO_CASSIS_NIR               -143423
      TGO_CASSIS_BLU               -143424

We likely want to expand the dictionary to include the filter from the label. Basically make the look up key:

key = super().instrument_id + "_" + self.label["IsisCube"]["Instrument"]["Filter"]

Then update the look up table with:

'CaSSIS_RED': 'TGO_CASSIS_RED',
'CaSSIS_NIR': 'TGO_CASSIS_NIR',
...

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.

ISIS keys the CaSSIS camera on the base frame -143400 for every filter, not the per-filter codes. Spice::init prefers NaifFrameCode over NaifIkCode, and TgoCassisCamera reads the boresight, focal-plane map, and distortion from that code. Verified on real PAN and NIR cubes, both carry NaifFrameCode -143400. So the single lookup entry matches ISIS, and keying on the filter would diverge from it. The driver now reads the values from the furnished addendum for that code.

Comment thread ale/drivers/tgo_drivers.py Outdated
return -143420

@property
def focal_length(self):

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Similarly above, all of these added properties have the potential to be different in the IAK based on the NAIF ID. As of the latest addendum (007) they are all the same

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.

Agreed they are equal at 007. And since ISIS uses only the base -143400 values regardless (NaifFrameCode overrides the per-filter NaifIkCode), the per-code differences never reach the camera. The driver now reads these from the furnished addendum instead of hardcoding, so a newer addendum is picked up automatically.

Comment thread ale/drivers/tgo_drivers.py Outdated
Comment on lines +157 to +159
line (INS-143400_BORESIGHT_LINE = 1024.5) is addendum-only, so hardcoded.
"""
return 1024.5 - 0.5

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Per the IAK, if we handle each filter as ISIS does this will be different based on the filter:

 INS-143400_BORESIGHT_LINE   = 1024.5

 INS-143421_BORESIGHT_LINE   = 493.5

 INS-143422_BORESIGHT_LINE   = 839.5

 INS-143423_BORESIGHT_LINE   = 1175.5

 INS-143424_BORESIGHT_LINE   = 1516.5

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.

The camera uses INS-143400_BORESIGHT_LINE = 1024.5 for all filters, because TgoCassisCamera builds on naifIkCode() = -143400 (NaifFrameCode wins over NaifIkCode). A PAN cube reprojects ISIS vs CSM to about 7e-4 px median with 1024.5, which the per-filter 493.5 would not. This is now read from the addendum rather than hardcoded.

return [0.0, 100.0, 0.0]

@property
def usgscsm_distortion_model(self):

@acpaquette acpaquette Jul 20, 2026

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Looking at the distortion in USGSCSM, we are using:

static const double cassisFocalBound = 0.5 * 0.01 * 2048.0 + 0.2;

For both width and height of the detector to check that we are within the image. ISIS applies a slightly different check and uses the FILTER_LINES and FILTER_SAMPLES from here based on the NAIF ID:

 INS-143421_FILTER_LINES     = 280
 INS-143421_FILTER_SAMPLES   = 2048

 INS-143422_FILTER_LINES     = 256
 INS-143422_FILTER_SAMPLES   = 2048

 INS-143423_FILTER_LINES     = 256
 INS-143423_FILTER_SAMPLES   = 2048

 INS-143424_FILTER_LINES     = 256
 INS-143424_FILTER_SAMPLES   = 2048

It would be best if these values were baked into the distortion array's of the ISD and accessed within USGSCSM

@oleg-alexandrov oleg-alexandrov Jul 21, 2026

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.

For the -143400 code the camera uses, INS-143400_FILTER_SAMPLES and FILTER_LINES are both 2048, so the USGSCSM bound 0.50.012048+0.2 already matches ISIS. The per-filter 256/280 belong to the -14342x codes, which ISIS does not use to build this camera: TgoCassisCamera keys the distortion map on naifIkCode() = -143400. The bound only differs outside the CCD where the model is identity either way, so no ISD or USGSCSM change is needed here, because all logic is already as in ISIS.

Instead of hardcoding the addendum-only CaSSIS values, furnish the ISIS
addendum from the data area, auto-detecting the latest version, and read the
focal length, distortion, boresight, focal-plane transforms, and light-time
flags from the SPICE pool. Fall back to the latest known constants only when
the addendum cannot be furnished. Add tests that furnish a faux addendum and
assert the driver returns its value, proving the read path. The ISIS and CSM
cameras still agree to the same tolerance, verified with cam_test.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017UAsYR1UURD4nMBE4afn7G
@oleg-alexandrov

oleg-alexandrov commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator Author

Update: rather than hardcoding the addendum values, the driver now furnishes the ISIS addendum from the data area, auto-detecting the latest version, and reads the focal length, distortion, boresight, focal-plane transforms, and light-time flags from the SPICE pool, falling back to the latest known constants only when the addendum is not furnished. This lets the values track the addendum and its version rather than a frozen copy.

A new unite test was added that furnishes a faux addendum with a distinctive focal length and asserts the driver returns it, proving the read path, and another asserts the fallback when no addendum is furnished.

The ASP cam_test tool shows the ISIS and CSM cameras still agree to the same tolerance as before this change, about 7e-4 px median and 0.013 px max, so this robustness fix does not change the result.

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