Count CRPIX from zero, as named_arrays does - #45
Merged
Conversation
roytsmart
force-pushed
the
fix/crpix-origin
branch
from
August 14, 2026 21:51
825583d to
c9a3585
Compare
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #45 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 16 16
Lines 536 561 +25
=========================================
+ Hits 536 561 +25
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
roytsmart
force-pushed
the
fix/crpix-origin
branch
3 times, most recently
from
August 15, 2026 16:25
05316c6 to
e616b94
Compare
`astropy.wcs` hands back the keyword as the header writes it, and FITS counts pixels from one. The formula it is put into is the one in the WCS paper and is written out correctly, but the pixel coordinates given to it come from `named_arrays.indices` and so start at zero. Measuring the reference point from one end of the first pixel and the pixels themselves from the other moves every observation by one pixel. On a raster that is a third of an arcsecond across and a sixth along the slit. On the wavelength axis it is about 3 km/s of Doppler shift, which is the one that would go unremarked, since it looks like a velocity rather than like a mistake. The coordinates are now checked against `astropy.wcs` on all three axes, built from the same file so that there is nothing else the two could disagree about. The projection is taken off first: `AbstractWcsVector` is the linear part of the transformation, and over a field this size the projection is worth a few times ten to the minus five arcseconds, far below the pixel this is looking for. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011q4461XE8hCcZCKsViMQC1
roytsmart
force-pushed
the
fix/crpix-origin
branch
from
August 15, 2026 17:15
e616b94 to
f426345
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
SpectrographObservation.from_fitsput theCRPIXkeywords intonamed_arrays.AbstractWcsVectorexactly asastropy.wcsreported them,and
astropyreports them as the header writes them, which FITS countsfrom one.
The formula they are used in is the one in the WCS paper and is written
out correctly:
but
pcomes fromnamed_arrays.indicesand so counts from zero, whilerarrived counting from one. Subtracting one from the other mixes thetwo conventions and moves everything by a pixel. The
- 0.5alreadythere is a separate thing: it turns cell centers into the cell edges this
grid is built on, and says nothing about where counting starts.
Measured on
iris_l2_20210923_...:cdeltis positive, so wavelengths came out one pixel low and velocitiescarried a systematic blue bias of about 3 km/s. That is the one worth
noting: an offset in arcseconds looks like an offset, while an offset in
wavelength looks like a Doppler shift.
Testing
test_inputs_against_astropy_wcsasksastropy.wcsthe same question onall three axes, at four places in the cube. It is built with
from_fitsfrom one file rather than from a time range, so the coordinates and the
keywords they are checked against come from the same file.
The projection is taken off before comparing, since
AbstractWcsVectoristhe linear part of the transformation and does not apply one. Left in, it
contributes about 2.5e-5 arcsec, which is nowhere near the pixel being
looked for, but taking it out makes the two answers the same answer
rather than nearly the same.
Reverting the fix fails the new test by 9.8e-5 deg, which is 0.353″, one
pixel across the raster. The 16 tests in
iris/sg/_spectrograph_test.pypass with it.
Related
The same bug is open against AIA as sun-data/solar-dynamics-observatory#21,
and was fixed for HMI in sun-data/solar-dynamics-observatory#20. Those
three are the only places in the group's packages that read
CRPIXfrom aheader.
Anything already derived from these coordinates moves by a pixel, so
results built on this will shift.
🤖 Generated with Claude Code
https://claude.ai/code/session_011q4461XE8hCcZCKsViMQC1