From 4ba6af54e57e1bb2e287a90ae58f226313b0e638 Mon Sep 17 00:00:00 2001 From: Simon Walker Date: Tue, 10 Feb 2026 09:56:23 +0000 Subject: [PATCH] Fix axis ordering in read_region/write_region to match C row-major convention create_image and fetch_hdu_info reverse dimensions to present them in C row-major order, but read_region and write_region were passing ranges directly to CFITSIO without reversing. This caused the ranges to be interpreted with swapped axes. Co-Authored-By: Claude Opus 4.6 --- fitsio/src/fitsfile.rs | 4 ++-- fitsio/src/images.rs | 14 +++++++++----- fitsio/tests/test_square_array.rs | 5 +++-- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/fitsio/src/fitsfile.rs b/fitsio/src/fitsfile.rs index 1ec95a07..3efb599d 100644 --- a/fitsio/src/fitsfile.rs +++ b/fitsio/src/fitsfile.rs @@ -1401,8 +1401,8 @@ mod test { .unwrap(); assert_eq!(read_data.len(), (6 - 2) * (17 - 11) * (7 - 3)); - assert_eq!(read_data[0], 614); - assert_eq!(read_data[50], 958); + assert_eq!(read_data[0], 689); + assert_eq!(read_data[50], 1223); }); } diff --git a/fitsio/src/images.rs b/fitsio/src/images.rs index a7dd0bde..5942d01d 100644 --- a/fitsio/src/images.rs +++ b/fitsio/src/images.rs @@ -166,7 +166,9 @@ macro_rules! read_image_impl_vec { let mut lpixel = Vec::with_capacity(n_ranges); let mut nelements = 1; - for range in ranges { + // Reverse the ranges to match CFITSIO's Fortran column-major + // convention, since the user provides ranges in C row-major order + for range in ranges.iter().rev() { let start = range.start + 1; // No +1 as the range is exclusive let end = range.end; @@ -254,7 +256,9 @@ macro_rules! write_image_impl { let mut fpixel = Vec::with_capacity(n_ranges); let mut lpixel = Vec::with_capacity(n_ranges); - for range in ranges { + // Reverse the ranges to match CFITSIO's Fortran column-major + // convention, since the user provides ranges in C row-major order + for range in ranges.iter().rev() { let start = range.start + 1; // No +1 as the range is exclusive let end = range.end; @@ -441,8 +445,8 @@ mod tests { let chunk: Vec = hdu.read_region(&mut f, &[&ycoord, &xcoord]).unwrap(); assert_eq!(chunk.len(), (7 - 5) * (3 - 2)); - assert_eq!(chunk[0], 168); - assert_eq!(chunk[chunk.len() - 1], 112); + assert_eq!(chunk[0], 101); + assert_eq!(chunk[chunk.len() - 1], 171); } #[test] @@ -494,7 +498,7 @@ mod tests { let chunk: Vec = hdu.read_region(&mut f, &[&(0..10), &(0..5)]).unwrap(); assert_eq!(chunk.len(), 10 * 5); assert_eq!(chunk[0], 50); - assert_eq!(chunk[25], 80); + assert_eq!(chunk[25], 75); }); } diff --git a/fitsio/tests/test_square_array.rs b/fitsio/tests/test_square_array.rs index ea8b0c5a..85be610a 100644 --- a/fitsio/tests/test_square_array.rs +++ b/fitsio/tests/test_square_array.rs @@ -10,8 +10,9 @@ fn test_square_array() { * 15, 16, 17, 18, 19, * 20, 21, 22, 23, 24] * - * We check that the x-values (1..3) (exclusive of the top end), and y-values (2..4) + * We check that rows (1..3) (exclusive of the top end), and columns (2..4) * (exclusive of the top end) return what we expect. + * Ranges follow C row-major convention: [rows, columns]. */ let filename = "../testdata/square_array.fits"; let mut f = FitsFile::open(filename).unwrap(); @@ -19,5 +20,5 @@ fn test_square_array() { let ranges = vec![&(1..3), &(2..4)]; let data: Vec = phdu.read_region(&mut f, &ranges).unwrap(); - assert_eq!(data, vec![11, 12, 16, 17]); + assert_eq!(data, vec![7, 8, 12, 13]); }