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}