use crate::misc::*;
use crate::rfinput::*;
use log::trace;
use std::fmt;
#[cfg(any(feature = "python", feature = "python-stubgen"))]
use pyo3::prelude::*;
#[cfg(feature = "python-stubgen")]
use pyo3_stub_gen_derive::gen_stub_pyclass;
#[cfg(test)]
mod test;
fn fine_pfb_reorder(input: usize) -> usize {
((input) & 0xc0) | (((input) & 0x03) << 4) | (((input) & 0x3c) >> 2)
}
#[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)]
pub(crate) struct LegacyConversionBaseline {
pub baseline: usize, pub ant1: usize, pub ant2: usize, pub xx_index: usize, pub xx_conjugate: bool, pub xy_index: usize, pub xy_conjugate: bool, pub yx_index: usize, pub yx_conjugate: bool, pub yy_index: usize, pub yy_conjugate: bool, }
impl LegacyConversionBaseline {
fn new(baseline: usize, ant1: usize, ant2: usize, xx: i32, xy: i32, yx: i32, yy: i32) -> Self {
Self {
baseline,
ant1,
ant2,
xx_index: xx.unsigned_abs() as usize,
xx_conjugate: xx < 0,
xy_index: xy.unsigned_abs() as usize,
xy_conjugate: xy < 0,
yx_index: yx.unsigned_abs() as usize,
yx_conjugate: yx < 0,
yy_index: yy.unsigned_abs() as usize,
yy_conjugate: yy < 0,
}
}
}
impl fmt::Debug for LegacyConversionBaseline {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(
f,
"{},{},{},{},{},{},{},{},{},{},{}",
self.baseline,
self.ant1,
self.ant2,
self.xx_index,
if self.xx_conjugate {
self.xx_index as isize
} else {
-(self.xx_index as isize)
},
self.xy_index, if self.xy_conjugate {
self.xy_index as isize
} else {
-(self.xy_index as isize)
},
self.yx_index, if self.yx_conjugate {
self.yx_index as isize
} else {
-(self.yx_index as isize)
},
self.yy_index, if self.yy_conjugate {
self.yy_index as isize
} else {
-(self.yy_index as isize)
}
)
}
}
fn generate_full_matrix(mwax_order: Vec<usize>) -> Vec<i32> {
let mut row1st: usize;
let mut row2nd: usize;
let mut col_a: usize;
let mut col_b: usize; assert_eq!(mwax_order.len(), 256);
let mut full_matrix: Vec<i32> = vec![-1; 65536];
let mut source_legacy_ndx: i32 = 0;
for col_order in (0..256).step_by(2) {
col_a = mwax_order[fine_pfb_reorder(col_order)]; col_b = mwax_order[fine_pfb_reorder(col_order + 1)];
for row_order in (0..=col_order).step_by(2) {
row1st = mwax_order[fine_pfb_reorder(row_order)];
row2nd = mwax_order[fine_pfb_reorder(row_order + 1)];
full_matrix[(row1st << 8) | col_a] = source_legacy_ndx; source_legacy_ndx += 1;
if col_order != row_order {
full_matrix[(row2nd << 8) | col_a] = source_legacy_ndx; }
source_legacy_ndx += 1; full_matrix[(row1st << 8) | col_b] = source_legacy_ndx; source_legacy_ndx += 1;
full_matrix[(row2nd << 8) | col_b] = source_legacy_ndx; source_legacy_ndx += 1;
}
}
for row_order in 0..256 {
for col_order in 0..256 {
if full_matrix[row_order << 8 | col_order] == -1 {
full_matrix[row_order << 8 | col_order] =
-(full_matrix[col_order << 8 | row_order]); }
}
}
full_matrix
}
pub(crate) fn generate_conversion_array(rf_inputs: &[Rfinput]) -> Vec<LegacyConversionBaseline> {
assert_eq!(rf_inputs.len(), 256);
let mut map = rf_inputs
.iter()
.map(|rf| (rf.input, rf.subfile_order))
.collect::<Vec<_>>();
map.sort_unstable();
let mwax_order = map
.into_iter()
.map(|(_, subfile_order)| subfile_order as usize)
.collect();
let full_matrix: Vec<i32> = generate_full_matrix(mwax_order);
let (mut xx, mut xy, mut yx, mut yy): (i32, i32, i32, i32); let mut baseline: usize = 0;
let baseline_count = get_baseline_count(128);
let mut conversion_table: Vec<LegacyConversionBaseline> = Vec::with_capacity(baseline_count);
for row_tile in 0..128 {
for col_tile in row_tile..128 {
xx = full_matrix[(row_tile * 2) << 8 | (col_tile * 2)] * 2;
xy = full_matrix[(row_tile * 2) << 8 | (col_tile * 2 + 1)] * 2;
yx = full_matrix[(row_tile * 2 + 1) << 8 | (col_tile * 2)] * 2;
yy = full_matrix[(row_tile * 2 + 1) << 8 | (col_tile * 2 + 1)] * 2;
conversion_table.push(LegacyConversionBaseline::new(
baseline, row_tile, col_tile, xx, xy, yx, yy,
));
baseline += 1;
}
}
assert_eq!(baseline, baseline_count);
assert_eq!(conversion_table.len(), baseline_count);
trace!("legacy_conversion_table: {:?}", conversion_table);
conversion_table
}
pub(crate) fn convert_legacy_hdu_to_mwax_baseline_order(
conversion_table: &[LegacyConversionBaseline],
input_buffer: &[f32],
output_buffer: &mut [f32],
num_fine_chans: usize,
) {
let num_baselines = get_baseline_count(128);
let floats_per_baseline_fine_chan = 8; let floats_per_fine_chan = num_baselines * floats_per_baseline_fine_chan;
let floats_per_baseline = floats_per_baseline_fine_chan * num_fine_chans;
assert!(input_buffer.len() >= num_fine_chans * floats_per_fine_chan);
assert!(output_buffer.len() >= num_fine_chans * floats_per_fine_chan);
for fine_chan_index in 0..num_fine_chans {
for (baseline_index, baseline) in conversion_table.iter().enumerate() {
let source_index = fine_chan_index * floats_per_fine_chan;
let destination_index = (baseline_index * floats_per_baseline)
+ (fine_chan_index * floats_per_baseline_fine_chan);
unsafe {
*output_buffer.get_unchecked_mut(destination_index) =
*input_buffer.get_unchecked(source_index + baseline.xx_index);
*output_buffer.get_unchecked_mut(destination_index + 1) = if baseline.xx_conjugate {
-input_buffer.get_unchecked(source_index + baseline.xx_index + 1)
} else {
*input_buffer.get_unchecked(source_index + baseline.xx_index + 1)
};
*output_buffer.get_unchecked_mut(destination_index + 2) =
*input_buffer.get_unchecked(source_index + baseline.xy_index);
*output_buffer.get_unchecked_mut(destination_index + 3) = if baseline.xy_conjugate {
-input_buffer.get_unchecked(source_index + baseline.xy_index + 1)
} else {
*input_buffer.get_unchecked(source_index + baseline.xy_index + 1)
};
*output_buffer.get_unchecked_mut(destination_index + 4) =
*input_buffer.get_unchecked(source_index + baseline.yx_index);
*output_buffer.get_unchecked_mut(destination_index + 5) = if baseline.yx_conjugate {
-input_buffer.get_unchecked(source_index + baseline.yx_index + 1)
} else {
*input_buffer.get_unchecked(source_index + baseline.yx_index + 1)
};
*output_buffer.get_unchecked_mut(destination_index + 6) =
*input_buffer.get_unchecked(source_index + baseline.yy_index);
*output_buffer.get_unchecked_mut(destination_index + 7) = if baseline.yy_conjugate {
-input_buffer.get_unchecked(source_index + baseline.yy_index + 1)
} else {
*input_buffer.get_unchecked(source_index + baseline.yy_index + 1)
};
*output_buffer.get_unchecked_mut(destination_index + 1) *= -1.0;
*output_buffer.get_unchecked_mut(destination_index + 3) *= -1.0;
*output_buffer.get_unchecked_mut(destination_index + 5) *= -1.0;
*output_buffer.get_unchecked_mut(destination_index + 7) *= -1.0;
}
}
}
}
pub(crate) fn convert_legacy_hdu_to_mwax_frequency_order(
conversion_table: &[LegacyConversionBaseline],
input_buffer: &[f32],
output_buffer: &mut [f32],
num_fine_chans: usize,
) {
let num_baselines = get_baseline_count(128);
let floats_per_baseline_fine_chan = 8; let floats_per_fine_chan = num_baselines * floats_per_baseline_fine_chan;
assert!(input_buffer.len() >= num_fine_chans * floats_per_fine_chan);
assert!(output_buffer.len() >= num_fine_chans * floats_per_fine_chan);
for fine_chan_index in 0..num_fine_chans {
for (baseline_index, baseline) in conversion_table.iter().enumerate() {
let source_index = fine_chan_index * floats_per_fine_chan;
let destination_index = source_index + (baseline_index * floats_per_baseline_fine_chan);
unsafe {
*output_buffer.get_unchecked_mut(destination_index) =
*input_buffer.get_unchecked(source_index + baseline.xx_index);
*output_buffer.get_unchecked_mut(destination_index + 1) = if baseline.xx_conjugate {
-input_buffer.get_unchecked(source_index + baseline.xx_index + 1)
} else {
*input_buffer.get_unchecked(source_index + baseline.xx_index + 1)
};
*output_buffer.get_unchecked_mut(destination_index + 2) =
*input_buffer.get_unchecked(source_index + baseline.xy_index);
*output_buffer.get_unchecked_mut(destination_index + 3) = if baseline.xy_conjugate {
-input_buffer.get_unchecked(source_index + baseline.xy_index + 1)
} else {
*input_buffer.get_unchecked(source_index + baseline.xy_index + 1)
};
*output_buffer.get_unchecked_mut(destination_index + 4) =
*input_buffer.get_unchecked(source_index + baseline.yx_index);
*output_buffer.get_unchecked_mut(destination_index + 5) = if baseline.yx_conjugate {
-input_buffer.get_unchecked(source_index + baseline.yx_index + 1)
} else {
*input_buffer.get_unchecked(source_index + baseline.yx_index + 1)
};
*output_buffer.get_unchecked_mut(destination_index + 6) =
*input_buffer.get_unchecked(source_index + baseline.yy_index);
*output_buffer.get_unchecked_mut(destination_index + 7) = if baseline.yy_conjugate {
-input_buffer.get_unchecked(source_index + baseline.yy_index + 1)
} else {
*input_buffer.get_unchecked(source_index + baseline.yy_index + 1)
};
*output_buffer.get_unchecked_mut(destination_index + 1) *= -1.0;
*output_buffer.get_unchecked_mut(destination_index + 3) *= -1.0;
*output_buffer.get_unchecked_mut(destination_index + 5) *= -1.0;
*output_buffer.get_unchecked_mut(destination_index + 7) *= -1.0;
}
}
}
}
pub(crate) fn convert_mwax_hdu_to_frequency_order(
input_buffer: &[f32],
output_buffer: &mut [f32],
num_baselines: usize,
num_fine_chans: usize,
num_visibility_pols: usize,
) {
let floats_per_baseline_fine_chan = num_visibility_pols * 2; let floats_per_baseline = num_fine_chans * floats_per_baseline_fine_chan; let floats_per_fine_chan = num_baselines * floats_per_baseline_fine_chan;
assert!(input_buffer.len() >= num_fine_chans * floats_per_fine_chan);
assert!(output_buffer.len() >= num_fine_chans * floats_per_fine_chan);
for baseline_index in 0..num_baselines {
for fine_chan_index in 0..num_fine_chans {
let source_index = (baseline_index * floats_per_baseline)
+ (fine_chan_index * floats_per_baseline_fine_chan);
let destination_index = (fine_chan_index * floats_per_fine_chan)
+ (baseline_index * floats_per_baseline_fine_chan);
output_buffer[destination_index..(floats_per_baseline_fine_chan + destination_index)]
.clone_from_slice(
&input_buffer[source_index..(floats_per_baseline_fine_chan + source_index)],
);
}
}
}