astrors/io/hdus/bintable/
bintablehdu.rs

1use std::fs::File;
2use std::io::Result;
3
4use polars::frame::DataFrame;
5use crate::io::hdus::bintable::bintable::*;
6
7use crate::io::header::card::Card;
8use crate::io::Header;
9
10const MANDATORY_KEYWORDS: [&str; 5] = [
11    "XTENSION",
12    "BITPIX",
13    "NAXIS",
14    "NAXIS1",
15    "NAXIS2",
16];
17
18/// Represents a Binary Table Header Data Unit (HDU) in a FITS file.
19///
20/// # Fields
21/// - `header` (Header): The FITS header containing metadata for the binary table.
22/// - `data` (DataFrame): The binary table's data stored as a Polars `DataFrame`.
23pub struct BinTableHDU{
24    pub header: Header,
25    pub data: DataFrame,
26}
27
28impl BinTableHDU {
29    /// Constructs a new `BinTableHDU` with the given header and data.
30    ///
31    /// # Arguments
32    /// - `header` (Header): The FITS header containing metadata for the binary table.
33    /// - `data` (DataFrame): The binary table's data.
34    ///
35    /// # Returns
36    /// - `BinTableHDU`: A new instance of the binary table HDU.
37    pub fn new(header: Header, data: DataFrame) -> Self {
38        Self {
39            header,
40            data,
41        }
42    }
43
44    /// Creates a new `BinTableHDU` with only data, initializing a basic header.
45    ///
46    /// # Arguments
47    /// - `data` (DataFrame): The binary table's data.
48    ///
49    /// # Returns
50    /// - `BinTableHDU`: A new instance with a basic header containing default binary table metadata.
51    pub fn new_data(data: DataFrame) -> Self {
52        let mut header = Header::new();
53        header.add_card(&Card::new("XTENSION".to_string(), "BINTABLE".to_string(), Some("Binary table".to_string())));
54        Self {
55            header,
56            data,
57        }
58    }
59
60    /// Reads a Binary Table HDU from a FITS file.
61    ///
62    /// # Arguments
63    /// - `f` (&mut File): The file from which to read the HDU.
64    ///
65    /// # Returns
66    /// - `Result<BinTableHDU>`: The `BinTableHDU` containing the header and data or an I/O error.
67    ///
68    /// # Behavior
69    /// - Reads the header to extract metadata.
70    /// - Reads and parses the binary table data into a Polars `DataFrame`.
71    /// - Extracts column metadata from the header for data interpretation.
72    pub fn read_from_file(f: &mut File) -> Result<Self>  {
73        //TODO: Check for mandatory words
74        let mut header = Header::new();
75        header.read_from_file(f)?;
76        let mut columns = read_tableinfo_from_header(&header).unwrap();
77        let df = read_table_bytes_to_df(&mut columns, &header, f);
78        Ok(Self::new(header, df?))
79    }
80
81    /// Writes the Binary Table HDU to a FITS file.
82    ///
83    /// # Arguments
84    /// - `f` (&mut File): The file to which the HDU will be written.
85    ///
86    /// # Returns
87    /// - `Result<()>`: Returns `Ok(())` on success or an I/O error.
88    ///
89    /// # Behavior
90    /// - Ensures the header contains mandatory keywords in the correct order.
91    /// - Converts the Polars `DataFrame` into a binary buffer and writes it to the file.
92    /// - Updates the header with column metadata and writes it to the file.
93    pub fn write_to_file(&mut self, mut f: &mut File) -> Result<()> {
94        //TODO: This function should not repeat here and in primary hdu
95        self.header.fix_header_w_mandatory_order(&MANDATORY_KEYWORDS);
96        let columns = polars_to_columns(&self.data).unwrap();
97        create_table_on_header(&mut self.header, &columns, self.data.height() as i64);
98        
99        self.header.fix_header_w_mandatory_order(&MANDATORY_KEYWORDS);
100        self.header.write_to_buffer(&mut f)?;
101        df_to_buffer(columns, &self.data, f)?;
102        Ok(())
103    }
104}