Skip to content

Fix for very large number of samples#677

Merged
acpaquette merged 9 commits intoDOI-USGS:mainfrom
oleg-alexandrov:ephem_fix
Mar 23, 2026
Merged

Fix for very large number of samples#677
acpaquette merged 9 commits intoDOI-USGS:mainfrom
oleg-alexandrov:ephem_fix

Conversation

@oleg-alexandrov
Copy link
Copy Markdown
Collaborator

This is a proposed fix for the fact that ALE creates outrageously large linescan models, with one pose sample per line, which makes mapprojection and bundle adjustment almost unusable, as a huge amount of time is spent simply loading the cameras.

The fix is to produce one pose sample per 10 lines. This should be more than enough, given how little the camera poses change in orbit.

There is no reason to think the current approach of one sample per line is more accurate. All of these interpolate into the true number of samples recorded in spice in either case. Then, in the usgscsm linescan model, there's additional Lagrange interpolation.

I tested this very carefully for LRO NAC, and I will be using this for more than 1000 images for a Moon map project. Projecting from the camera to the ground and back brings one to within 0.061 pixels of starting pixel.

Maybe a different fix is desired, as proposed in #655.

But I think there should be a sense of urgency for this as the problem is rather notable and the fix is rather simple.

Here are some good LRO NAC images to test with: M1285980578RE, M1104890331LE, M1104883188RE.

The ASP cam_test program can test old vs new implementation.

Licensing

This project is mostly composed of free and unencumbered software released into the public domain, and we are unlikely to accept contributions that are not also released into the public domain. Somewhere near the top of each file should have these words:

This work is free and unencumbered software released into the public domain. In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain.

  • 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.

Comment on lines +100 to +104
# A pose sample very 10 lines is more than enough. Otherwise
# the .json files become very large and very slow to load.
numSamples = max(self.image_lines/10, 100)
numSamples = min(numSamples, self.image_lines)
self._ephemeris_time = np.linspace(self.ephemeris_start_time, self.ephemeris_stop_time, numSamples + 1)
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.

This should be configurable in some way. We have used the props parameter on init to pass kwargs into the driver objects. We could check if it got mixed in; otherwise, use a default.

Sample at max(100, image_lines // 10) instead of one per line.
Large linescan images (e.g., Chandrayaan-2 TMC with 177k lines)
produced huge ISDs that were slow to generate and load.

Tested with CTX (Mars, 11k lines) and Chandrayaan-2 TMC (Moon, 177k
lines) via NaifSpice. Results:
- CTX: 0.000034 px max error, ISD 2.5 MB -> 0.3 MB, 3.3x faster load
- Ch2 TMC: 0.02 px max error, ISD 65 MB -> 6.5 MB, 8.7x faster load

The sample count can be overridden via props['num_ephem_samples'].

Removes the Chandrayaan-specific ephemeris_time override, now handled
by the general fix in the base class.
Eigen 5.0.1 on conda-forge is not accepted by find_package(Eigen3 3.3)
due to major version mismatch. The API is backward-compatible, so drop
the version requirement.
Update 20 reference ISD files to match the new ephemeris_time sampling
in type_sensor.py (max(25, image_lines // 10) instead of image_lines + 1).

Sample counts reduced ~4-10x depending on instrument. Position and
orientation values remain identical at shared times since SPICE
polynomial evaluation is exact regardless of query density.
Only apply 1:10 reduction when the result is at least 25 samples
(USGSCSM Lagrange interpolation minimum). For images under ~250 lines,
keep original one-per-line sampling to avoid unnecessary changes.

Formula: reduced = image_lines // 10 + 1
         num_samples = reduced if reduced >= 25 else image_lines + 1
Update 13 reference ISD files for large-image instruments where the
1:10 ephemeris reduction applies. Small-image ISDs are unchanged.

Fix pre-existing test_transformation floating-point comparison by
using assert_allclose with atol=1e-15 instead of assert_equal.
These ISDs were incorrectly regenerated with the old floor-of-100
formula. With the corrected formula, small images keep one-per-line
sampling, so their golden ISDs should match upstream main.
Only reduce sampling for images with 1000+ lines (where lines//10+1
>= 100). Smaller images keep one-per-line to preserve existing
behavior. Only 4 ISDs change: mexhrsc, mexhrsc_isis, mgsmocna, hirise.
@oleg-alexandrov
Copy link
Copy Markdown
Collaborator Author

oleg-alexandrov commented Mar 18, 2026

I updated the fix to this to ensure ISDs with less than 1000 lines are not modified as that was changing too many results. The custom fix for Chandraayaan got removed as it inherits it from the parent class.

Also: fixed a recent Eigen compile error. Added the ability to pass in a custom number of samples via the props field.
Added a 1e-15 tolerance for a test which was a little off on my machine.

Here is how results change when doing image to ground with old ISD and then back ground to image with new ISD, and back with the ASP cam_test. Here are max pixel abs difference result.

  • HiRISE from this test suite: 0.000108 px
  • MEX HRSC from this test suite (pds driver path): 0.093 px
  • MEX HRSC from this test suite (isis driver path): 0.000376 px
  • CTX (my own test) 0.000034 px
  • Chandrayaan-2 TMC (my own test): 0.020 px

Note that the resampling also works for the MGS MOC test. Number of samples is reduced properly. But this seems to be a funny test where rays do not point to ground, so the cam_test approach fails to validate. Manual inpsection looks ok.

Copy link
Copy Markdown
Collaborator

@acpaquette acpaquette left a comment

Choose a reason for hiding this comment

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

One change to address and a topic to discuss

Replace num_ephem_samples prop with reduction/ephem_sample_rate props
per reviewer request. reduction="linear" (default) subsamples every Nth
line; reduction=None keeps one-per-line. Remove OHRC ephemeris_time
override, now handled by base class.
Copy link
Copy Markdown
Collaborator

@acpaquette acpaquette left a comment

Choose a reason for hiding this comment

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

Just needs a Changelog entry and this should be good to go!

@oleg-alexandrov
Copy link
Copy Markdown
Collaborator Author

Added changelog. Tests pass.

@acpaquette acpaquette merged commit c2bae0e into DOI-USGS:main Mar 23, 2026
13 checks passed
@oleg-alexandrov oleg-alexandrov deleted the ephem_fix branch March 25, 2026 22:04
jrcain-usgs pushed a commit to jrcain-usgs/ale that referenced this pull request Mar 25, 2026
* Reduce ephemeris_time samples for linescan sensors

Sample at max(100, image_lines // 10) instead of one per line.
Large linescan images (e.g., Chandrayaan-2 TMC with 177k lines)
produced huge ISDs that were slow to generate and load.

Tested with CTX (Mars, 11k lines) and Chandrayaan-2 TMC (Moon, 177k
lines) via NaifSpice. Results:
- CTX: 0.000034 px max error, ISD 2.5 MB -> 0.3 MB, 3.3x faster load
- Ch2 TMC: 0.02 px max error, ISD 65 MB -> 6.5 MB, 8.7x faster load

The sample count can be overridden via props['num_ephem_samples'].

Removes the Chandrayaan-specific ephemeris_time override, now handled
by the general fix in the base class.

* Drop Eigen3 version constraint to support Eigen 5.x

Eigen 5.0.1 on conda-forge is not accepted by find_package(Eigen3 3.3)
due to major version mismatch. The API is backward-compatible, so drop
the version requirement.

* Regenerate golden ISDs for reduced ephemeris sampling

Update 20 reference ISD files to match the new ephemeris_time sampling
in type_sensor.py (max(25, image_lines // 10) instead of image_lines + 1).

Sample counts reduced ~4-10x depending on instrument. Position and
orientation values remain identical at shared times since SPICE
polynomial evaluation is exact regardless of query density.

* Fix ephemeris sampling formula for small images

Only apply 1:10 reduction when the result is at least 25 samples
(USGSCSM Lagrange interpolation minimum). For images under ~250 lines,
keep original one-per-line sampling to avoid unnecessary changes.

Formula: reduced = image_lines // 10 + 1
         num_samples = reduced if reduced >= 25 else image_lines + 1

* Regenerate golden ISDs and fix rotation test tolerance

Update 13 reference ISD files for large-image instruments where the
1:10 ephemeris reduction applies. Small-image ISDs are unchanged.

Fix pre-existing test_transformation floating-point comparison by
using assert_allclose with atol=1e-15 instead of assert_equal.

* Restore original ISDs for small-image instruments

These ISDs were incorrectly regenerated with the old floor-of-100
formula. With the corrected formula, small images keep one-per-line
sampling, so their golden ISDs should match upstream main.

* Raise ephemeris sampling floor to 100 and regenerate ISDs

Only reduce sampling for images with 1000+ lines (where lines//10+1
>= 100). Smaller images keep one-per-line to preserve existing
behavior. Only 4 ISDs change: mexhrsc, mexhrsc_isis, mgsmocna, hirise.

* Address review: rename props API, remove OHRC override

Replace num_ephem_samples prop with reduction/ephem_sample_rate props
per reviewer request. reduction="linear" (default) subsamples every Nth
line; reduction=None keeps one-per-line. Remove OHRC ephemeris_time
override, now handled by base class.

* Add changelog entry for ephemeris subsampling
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