use crate::{read_cell_array_f32, read_cell_value, Rfinput};
use std::fmt;
pub mod error;
use fitsio::hdu::{FitsHdu, HduInfo};
use fitsio::FitsFile;
#[cfg(any(feature = "python", feature = "python-stubgen"))]
use pyo3::prelude::*;
#[cfg(feature = "python-stubgen")]
use pyo3_stub_gen_derive::gen_stub_pyclass;
pub mod ffi;
#[cfg(test)]
pub(crate) mod ffi_test;
#[cfg(test)]
mod test;
#[cfg_attr(feature = "python-stubgen", gen_stub_pyclass)]
#[cfg_attr(
any(feature = "python", feature = "python-stubgen"),
pyclass(get_all, set_all, from_py_object)
)]
#[derive(Clone, Debug, PartialEq)]
pub struct CalibrationFit {
pub rf_input: Rfinput,
pub delay_metres: f32,
pub intercept_metres: f32,
pub gains: Vec<f32>,
pub num_gains: usize,
pub gain_polynomial_fit0: Vec<f32>,
pub num_gain_polynomial_fit0: usize,
pub gain_polynomial_fit1: Vec<f32>,
pub num_gain_polynomial_fit1: usize,
pub phase_fit_quality: f32,
pub gain_fit_quality: f32,
}
impl fmt::Display for CalibrationFit {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let gains: String = if !self.gains.is_empty() {
format!("[{}..{}]", self.gains[0], self.gains[self.gains.len() - 1])
} else {
"[]".to_string()
};
let gain_polynomial_fit0: String = if !self.gain_polynomial_fit0.is_empty() {
format!(
"[{}..{}]",
self.gain_polynomial_fit0[0],
self.gain_polynomial_fit0[self.gain_polynomial_fit0.len() - 1]
)
} else {
"[]".to_string()
};
let gain_polynomial_fit1: String = if !self.gain_polynomial_fit1.is_empty() {
format!(
"[{}..{}]",
self.gain_polynomial_fit1[0],
self.gain_polynomial_fit1[self.gain_polynomial_fit1.len() - 1]
)
} else {
"[]".to_string()
};
write!(
f,
"Rfinput: {:?} Delay (m): {} Intercept (m): {}, Gains: {}, GainPolyFit0: {}, GainPolyFit1: {}, PhaseFitQuality: {}, GainFitQuality: {}",
self.rf_input, self.delay_metres, self.intercept_metres, gains, gain_polynomial_fit0, gain_polynomial_fit1, self.phase_fit_quality, self.gain_fit_quality
)
}
}
pub(crate) fn populate_calibration_fits(
metafits_fptr: &mut FitsFile,
calibdata_hdu: &FitsHdu,
rf_inputs: &[Rfinput],
num_coarse_channels: usize,
) -> Result<Vec<CalibrationFit>, error::CalibrationFitError> {
let rows = match &calibdata_hdu.info {
HduInfo::TableInfo {
column_descriptions: _,
num_rows,
} => *num_rows,
_ => 0,
};
let mut cal_fit_vec: Vec<CalibrationFit> = Vec::new();
for row in 0..rows {
let antenna: u32 = read_cell_value::<u32>(metafits_fptr, calibdata_hdu, "Antenna", row)?;
let pol: String = read_cell_value::<String>(metafits_fptr, calibdata_hdu, "Pol", row)?;
let rf_input: Rfinput = rf_inputs
.iter()
.find(|&r| r.ant == antenna && r.pol.to_string() == pol)
.cloned()
.ok_or(
error::CalibrationFitError::NoRfInputFoundForCalibdataAntennaPol {
antenna: antenna as usize,
pol: pol.clone(),
},
)?;
let delay_metres: f32 =
match read_cell_value::<f32>(metafits_fptr, calibdata_hdu, "delay_m", row) {
Ok(val) => val,
Err(_) => read_cell_value::<f32>(metafits_fptr, calibdata_hdu, "Calib_Delay", row)?,
};
let intercept_metres: f32 =
read_cell_value::<f32>(metafits_fptr, calibdata_hdu, "Intercept", row)
.unwrap_or_default();
let gains: Vec<f32> = match read_cell_array_f32(
metafits_fptr,
calibdata_hdu,
"gains",
row,
num_coarse_channels,
) {
Ok(val) => val,
Err(_) => read_cell_array_f32(
metafits_fptr,
calibdata_hdu,
"Calib_Gains",
row,
num_coarse_channels,
)?,
};
let gain_polynomial_fit0: Vec<f32> = read_cell_array_f32(
metafits_fptr,
calibdata_hdu,
"gains_pol0",
row,
num_coarse_channels,
)
.unwrap_or_default();
let gain_polynomial_fit1: Vec<f32> = read_cell_array_f32(
metafits_fptr,
calibdata_hdu,
"gains_pol1",
row,
num_coarse_channels,
)
.unwrap_or_default();
let phase_fit_quality: f32 =
read_cell_value::<f32>(metafits_fptr, calibdata_hdu, "phase_fit_quality", row)
.unwrap_or_default();
let gain_fit_quality: f32 =
read_cell_value::<f32>(metafits_fptr, calibdata_hdu, "gain_fit_quality", row)
.unwrap_or_default();
cal_fit_vec.push(CalibrationFit {
rf_input,
delay_metres,
intercept_metres,
num_gains: gains.len(),
gains,
num_gain_polynomial_fit0: gain_polynomial_fit0.len(),
gain_polynomial_fit0,
num_gain_polynomial_fit1: gain_polynomial_fit1.len(),
gain_polynomial_fit1,
phase_fit_quality,
gain_fit_quality,
});
}
Ok(cal_fit_vec)
}