Expand description
§fitskit — Pure Rust FITS v4.0 reader/writer
A zero-dependency implementation of the FITS (Flexible Image Transport System) standard v4.0 for reading and writing astronomical data files.
§Supported HDU types
- Primary HDU — image data or header-only
- IMAGE extension — all BITPIX types (8, 16, 32, 64, -32, -64)
- ASCII TABLE extension — Aw, Iw, Fw.d, Ew.d, Dw.d column formats
- BINTABLE extension — all type codes including variable-length arrays (P/Q descriptors)
Tile-compressed images (ZIMAGE) are supported for reading integer and float
images (RICE_1, PLIO_1, HCOMPRESS_1; GZIP_1/GZIP_2 behind the gzip
feature), including float quantization with SUBTRACTIVE_DITHER_1/_2, via
Hdu::as_compressed_image +
CompressedImage::decompress.
Writing tile-compressed images is supported for RICE_1 (integer + quantized
float) and GZIP_1/GZIP_2 (integer; lossless float via GZIP_1) via
ImageData::compress /
compress_image, producing standard, cfitsio-
readable (funpack-decodable) compressed FITS. PLIO_1/HCOMPRESS_1 encoding and
random groups are not supported.
§Quick start — reading
use fitskit::{FitsFile, HduData, PixelData};
let fits = FitsFile::from_file("image.fits").unwrap();
// Access the primary HDU
let primary = fits.primary();
println!("BITPIX = {}", primary.header.get_int("BITPIX").unwrap());
if let HduData::Image(img) = &primary.data {
println!("{}x{}", img.width().unwrap(), img.height().unwrap());
if let PixelData::F32(pixels) = &img.pixels {
println!("first pixel = {}", pixels[0]);
}
}
// Iterate over extensions
for hdu in fits.extensions() {
match &hdu.data {
HduData::Image(_) => println!("IMAGE extension"),
HduData::BinTable(t) => println!("BINTABLE: {} rows", t.nrows),
HduData::AsciiTable(t) => println!("TABLE: {} rows", t.nrows),
HduData::Empty => println!("empty"),
}
}§Quick start — writing
use fitskit::{FitsFile, Hdu, ImageData, PixelData, HeaderValue};
// Create a 100x100 16-bit image
let pixels: Vec<i16> = (0..10000).map(|i| (i % 1000) as i16).collect();
let img = ImageData::new(vec![100, 100], PixelData::I16(pixels));
let mut fits = FitsFile::with_primary_image(img);
fits.primary_mut().header.set("OBJECT", HeaderValue::String("M31".into()), None);
let bytes = fits.to_bytes().unwrap();
assert_eq!(bytes.len() % 2880, 0); // block-aligned§Binary tables
Build a BINTABLE extension column-by-column, then push it onto a file:
use fitskit::{FitsFile, Hdu, BinTableBuilder, BinColumnType};
let table = BinTableBuilder::new()
.add_column("RA", BinColumnType::D64(1))
.add_column("DEC", BinColumnType::D64(1))
.add_column("MAG", BinColumnType::E32(1))
.push_row(|row| {
row.write_f64(180.0);
row.write_f64(45.0);
row.write_f32(12.5);
})
.build();
let mut fits = FitsFile::with_empty_primary();
fits.push_extension(Hdu::bintable_extension(table));
let _ = fits.to_bytes().unwrap();§Tile-compressed images
ImageData::compress produces a compressed-image
BINTABLE HDU; Hdu::as_compressed_image +
CompressedImage::decompress read it
back. RICE_1 is lossless for integers, so this round-trips exactly:
use fitskit::{FitsFile, ImageData, PixelData, CompressOptions, HduData};
let pixels: Vec<i16> = (0..10000).map(|i| (i % 1000) as i16).collect();
let img = ImageData::new(vec![100, 100], PixelData::I16(pixels.clone()));
// Compress (default: RICE_1, one tile per row) into a BINTABLE HDU and write it.
let mut fits = FitsFile::with_empty_primary();
fits.push_extension(img.compress(&CompressOptions::default()).unwrap());
let bytes = fits.to_bytes().unwrap();
// Read back and decompress.
let fits2 = FitsFile::from_bytes(&bytes).unwrap();
let cimg = fits2.extensions()[0].as_compressed_image().unwrap();
let restored = cimg.decompress().unwrap();
assert!(matches!(restored.pixels, PixelData::I16(ref v) if *v == pixels));RICE_1, PLIO_1, and HCOMPRESS_1 work in the default build. The GZIP_1/
GZIP_2 algorithms (selected via CompressOptions { algorithm: CompressionType::Gzip1, .. }, or encountered when decoding a GZIP-compressed
tile) require the gzip feature.
§BSCALE/BZERO
Physical values are computed as BZERO + BSCALE * array_value. The unsigned
integer convention stores unsigned values in signed storage:
use fitskit::{ImageData, PixelData};
// Unsigned u16 via BZERO=32768
let img = ImageData::new(vec![3], PixelData::I16(vec![-32768, 0, 32767]));
let physical = img.scaled_values(1.0, 32768.0);
assert_eq!(physical, vec![0.0, 32768.0, 65535.0]);§Checksums
Write with CHECKSUM/DATASUM integrity keywords:
use fitskit::{FitsFile, ImageData, PixelData};
let img = ImageData::new(vec![4], PixelData::U8(vec![1, 2, 3, 4]));
let fits = FitsFile::with_primary_image(img);
let bytes = fits.to_bytes_with_checksum().unwrap();
// Read back and verify
let fits2 = FitsFile::from_bytes(&bytes).unwrap();
fits2.primary().verify_datasum().unwrap();§Core types
A FITS file is an ordered sequence of Header-Data Units (HDUs):
FitsFile— top-level container (Vec<Hdu>); reads/writes files, bytes, or anyRead/Write, plus builder methods.Hdu— one HDU: aHeaderplus anHduDatapayload.HduData— payload enum:Empty,Image,AsciiTable,BinTable.Header/Keyword/HeaderValue— ordered cards with typed accessors.ImageData/PixelData— axes plus a typed pixel buffer; raw and BSCALE/BZERO-scaled access.BinTable/BinColumn/BinColumnType/BinCellValue— binary-table model (with VLA heap), built viaBinTableBuilder.AsciiTable— ASCIITABLEmodel.CompressedImage/CompressionType/CompressOptions— tile-compression read view and write options.Bitpix— theBITPIXdata type;Error/Result— error handling.
§Image-crate interop (feature image)
With the image feature, ImageData converts to and from the
image crate’s DynamicImage — e.g. to
save a FITS image as a PNG, or to ingest a raster as FITS.
use fitskit::{FitsFile, HduData, ImageData};
let fits = FitsFile::from_file("image.fits").unwrap();
if let HduData::Image(img) = &fits.primary().data {
// FITS -> image crate (BSCALE/BZERO applied; 1.0/0.0 = identity)
let dynamic = img.to_dynamic_image(1.0, 0.0).unwrap();
// image crate -> FITS, returning (ImageData, bscale, bzero)
let (restored, _bscale, _bzero) = ImageData::from_dynamic_image(&dynamic).unwrap();
assert_eq!(restored.axes, img.axes);
}§World Coordinate System (WCS)
With the wcs feature, parse the celestial WCS from a header and map between
1-based FITS pixel coordinates and world coordinates (degrees). The spherical
projection math is backed by the zero-dependency
mapproj crate.
use fitskit::FitsFile;
let fits = FitsFile::from_file("image.fits").unwrap();
let wcs = fits.primary().header.wcs().unwrap();
// Pixel (1-based) -> world (lon, lat) in degrees
let (ra, dec) = wcs.pixel_to_world(256.5, 256.5).unwrap();
// ...and back
let (x, y) = wcs.world_to_pixel(ra, dec).unwrap();Only the common two-axis celestial case (e.g. RA---TAN/DEC--TAN) is
supported; SIP distortions and 3+-axis/spectral WCS are out of scope. See the
wcs module docs for details.
§Feature flags
image— enables conversion betweenImageDataand theimagecrate’sDynamicImage.gzip— enables encoding and decoding ofGZIP_1/GZIP_2tile-compressed images via the pure-Rustminiz_oxidecrate. The default build stays dependency-free;RICE_1(read and write),PLIO_1, andHCOMPRESS_1decoding all work without this feature.wcs— enables two-axis celestial World Coordinate System pixel <-> world transforms (Wcs,Header::wcs) backed by the zero-dependencymapprojcrate. The default build stays dependency-free.
Re-exports§
pub use ascii_table::AsciiTable;pub use bintable::BinCellValue;pub use bintable::BinColumn;pub use bintable::BinColumnType;pub use bintable::BinTable;pub use bintable::BinTableBuilder;pub use error::Error;pub use error::Result;pub use fits::FitsFile;pub use hdu::Hdu;pub use hdu::HduData;pub use header::Header;pub use image_data::ImageData;pub use image_data::PixelData;pub use keyword::HeaderValue;pub use keyword::Keyword;pub use tile_compress::compress_image;pub use tile_compress::CompressOptions;pub use tile_compress::CompressedImage;pub use tile_compress::CompressionType;pub use tile_compress::Quantize;pub use tile_compress::TileGeometry;pub use types::Bitpix;pub use wcs::Wcs;
Modules§
- ascii_
table - bintable
- checksum
- FITS checksum computation per the FITS Checksum Proposal (Seaman, Pence, Rots 2012).
- error
- fits
- hdu
- header
- image_
conv - image_
data - io_
utils - keyword
- tile_
compress - Tiled image compression (the BINTABLE-based compressed-image convention).
- types
- wcs
- World Coordinate System (WCS) pixel <-> world transforms (feature
wcs).