astro-metadata 0.4.0

Metadata handling for astronomical images
docs.rs failed to build astro-metadata-0.4.0
Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.

astro-metadata

Metadata extraction and handling for astronomical images.

Overview

astro-metadata provides functionality for extracting and processing metadata from astronomical image formats, including FITS and XISF. It handles parsing of headers, extraction of equipment information, exposure details, and more.

Features

  • Comprehensive metadata type definitions
  • FITS header parsing
  • XISF header parsing
  • Equipment information (telescope, camera, etc.)
  • Exposure details
  • Filter information
  • Environmental data
  • Coordinate and timing utilities

Windows FITS Path-Length Note

On Windows, FITS file access in AstroMuninn and the ravensky-astro FITS APIs depends on CFITSIO (via fitsio / fitsio-sys). CFITSIO currently opens disk files using its fopen-based path handling (file_openfile), which in this environment follows the classic Windows path-length boundary.

Use full FITS paths shorter than 260 characters (< 260). At 260 or more, FITS open calls may fail.

This limitation is specific to FITS access through CFITSIO. XISF handling is not affected.

Installation

Add to your Cargo.toml:

[dependencies]
astro-metadata = "0.4.0"

API Reference

Core Types

AstroMetadata

pub struct AstroMetadata {
    pub equipment: Equipment,
    pub detector: Detector,
    pub filter: Filter,
    pub exposure: Exposure,
    pub mount: Option<Mount>,
    pub environment: Option<Environment>,
    pub wcs: Option<WcsData>,
    pub xisf: Option<XisfMetadata>,
    pub color_management: Option<ColorManagement>,
    pub attachments: Vec<AttachmentInfo>,
    pub raw_header_cards: Vec<FitsHeaderCard>,
    pub raw_headers: HashMap<String, String>,
}

Key methods:

impl AstroMetadata {
    /// Check if we have enough information to calculate plate scale
    pub fn can_calculate_plate_scale(&self) -> bool

    /// Calculate plate scale in arcsec/pixel
    pub fn plate_scale(&self) -> Option<f32>
    
    /// Calculate field of view in arcminutes
    pub fn field_of_view(&self) -> Option<(f32, f32)>
    
    /// Calculate the session date using location information if available
    pub fn calculate_session_date(&mut self)
}

Equipment

pub struct Equipment {
    pub telescope_name: Option<String>,
    pub focal_length: Option<f32>,
    pub aperture: Option<f32>,
    pub focal_ratio: Option<f32>,
    pub reducer_flattener: Option<String>,
    pub mount_model: Option<String>,
    pub focuser_position: Option<i32>,
    pub focuser_temperature: Option<f32>,
}

Detector

pub struct Detector {
    pub camera_name: Option<String>,
    pub pixel_size: Option<f32>,
    pub width: usize,
    pub height: usize,
    pub binning_x: usize,
    pub binning_y: usize,
    pub gain: Option<f32>,
    pub offset: Option<i32>,
    pub readout_mode: Option<String>,
    pub usb_limit: Option<String>,
    pub read_noise: Option<f32>,
    pub full_well: Option<f32>,
    pub temperature: Option<f32>,
    pub temp_setpoint: Option<f32>,
    pub cooler_power: Option<f32>,
    pub cooler_status: Option<String>,
    pub rotator_angle: Option<f32>,
}

Filter

pub struct Filter {
    pub name: Option<String>,
    pub position: Option<usize>,
    pub wavelength: Option<f32>,
}

Exposure

pub struct Exposure {
    pub object_name: Option<String>,
    pub ra: Option<f64>,
    pub dec: Option<f64>,
    pub date_obs: Option<DateTime<Utc>>,
    pub session_date: Option<DateTime<Utc>>,
    pub exposure_time: Option<f32>,
    pub frame_type: Option<String>,
    pub sequence_id: Option<String>,
    pub frame_number: Option<usize>,
    pub dither_offset_x: Option<f32>,
    pub dither_offset_y: Option<f32>,
    pub project_name: Option<String>,
    pub session_id: Option<String>,
}

FITS Parser

/// Extract metadata from a FITS file path
pub fn extract_metadata_from_path(path: &Path) -> Result<AstroMetadata>

/// Extract metadata from a FITS file
pub fn extract_metadata(fits_file: &mut FitsFile) -> Result<AstroMetadata>

/// Parse sexagesimal format (HH MM SS or DD MM SS) to decimal degrees
pub fn parse_sexagesimal(value: &str) -> Option<f64>
  • Parameters:
    • path: Path to the FITS file
    • fits_file: Open FITS file handle
    • value: String in sexagesimal format (e.g., "12 34 56" for RA or "-45 12 34" for DEC)
  • Returns:
    • AstroMetadata: Extracted metadata structure
    • f64: Decimal degrees (for parse_sexagesimal)
  • Errors:
    • If the file cannot be opened
    • If required headers cannot be read
    • On Windows, FITS open may fail when the full pathname is 260 characters or longer due to CFITSIO fopen path handling.

XISF Parser

/// Extract metadata from an XISF file path
pub fn extract_metadata_from_path(path: &Path) -> Result<AstroMetadata>

/// Extract metadata from an XISF file
pub fn extract_metadata<R: Read + Seek>(reader: &mut R) -> Result<AstroMetadata>
  • Parameters:
    • path: Path to the XISF file
    • reader: Reader for the XISF file
  • Returns:
    • AstroMetadata: Extracted metadata structure
  • Errors:
    • If the file cannot be opened
    • If the XISF signature is invalid
    • If the XML header cannot be parsed

Usage Examples

Extracting metadata from a FITS file

use astro_metadata::fits_parser;
use std::path::Path;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let path = Path::new("/path/to/image.fits");
    let metadata = fits_parser::extract_metadata_from_path(path)?;
    
    // Access equipment information
    if let Some(focal_length) = metadata.equipment.focal_length {
        println!("Focal length: {} mm", focal_length);
    }
    
    // Access exposure information
    if let Some(exp_time) = metadata.exposure.exposure_time {
        println!("Exposure time: {} seconds", exp_time);
    }
    
    // Calculate plate scale
    if let Some(plate_scale) = metadata.plate_scale() {
        println!("Plate scale: {} arcsec/pixel", plate_scale);
    }
    
    // Calculate field of view
    if let Some((width, height)) = metadata.field_of_view() {
        println!("Field of view: {:.2}' × {:.2}'", width, height);
    }
    
    Ok(())
}

Parsing sexagesimal coordinates

use astro_metadata::fits_parser::parse_sexagesimal;

fn main() {
    // Parse right ascension: "12 34 56" (12h 34m 56s)
    let ra_deg = parse_sexagesimal("12 34 56").map(|ra| ra * 15.0); // Convert hours to degrees
    println!("RA: {:?} degrees", ra_deg);
    
    // Parse declination: "-45 12 34" (-45° 12' 34")
    let dec_deg = parse_sexagesimal("-45 12 34");
    println!("DEC: {:?} degrees", dec_deg);
}

License

This project is dual-licensed under the MIT License or the Apache License, Version 2.0.