mod fld_file_loader;
pub use fld_file_loader::{DataCoordinates, DataDimensionality, FileData};
use std::collections::BTreeMap;
#[derive(Clone, Debug)]
pub struct B1Data {
pub file_name: String,
pub geo_keys: Vec<[i32; 3]>,
pub b1_vals: Vec<f64>,
}
impl B1Data {
pub fn from_file(path_and_name: String) -> Self {
let file_data = match FileData::load_file(path_and_name, 1) {
Ok(fd) => fd,
Err(msg) => panic!("{}", msg),
};
let file_name = file_data.file_name;
let geo_keys = file_data
.geo_points
.iter()
.map(|geo_floats| gen_geo_key(geo_floats))
.collect();
let b1_vals = file_data.fld_points.iter().flatten().copied().collect();
Self {
file_name,
geo_keys,
b1_vals,
}
}
}
#[derive(Clone, Debug)]
pub struct HDataGroup {
pub file_names: Vec<String>,
pub geo_keys: Vec<[i32; 3]>,
pub ch_h_vals: Vec<Vec<[f64; 6]>>,
pub num_points: usize,
}
impl HDataGroup {
pub fn from_files(paths_and_names: Vec<String>, assert_geo_equality: bool) -> Self {
let file_datas: Vec<FileData> = paths_and_names
.iter()
.cloned()
.map(|pn| match FileData::load_file(pn, 6) {
Ok(fd) => fd,
Err(msg) => panic!("{}", msg),
})
.collect();
let num_points = file_datas[0].num_points;
for fd in file_datas.iter().skip(1) {
assert_eq!(
num_points, fd.num_points,
"H files do not have the same number of points!"
);
}
let file_names = file_datas.iter().map(|fd| fd.file_name.clone()).collect();
let geo_keys: Vec<[i32; 3]> = file_datas[0]
.geo_points
.iter()
.map(|geo_floats| gen_geo_key(geo_floats))
.collect();
if assert_geo_equality {
for fd in file_datas.iter().skip(1) {
for (key, geo_pt) in geo_keys.iter().zip(fd.geo_points.iter()) {
assert_eq!(
key,
&gen_geo_key(geo_pt),
"H files do not cover the same geometry!"
);
}
}
}
let ch_h_vals = file_datas
.iter()
.map(|fd| {
fd.fld_points
.iter()
.map(|fld_pt| {
[
fld_pt[0], fld_pt[1], fld_pt[2], fld_pt[3], fld_pt[4], fld_pt[5],
]
})
.collect()
})
.collect();
Self {
file_names,
geo_keys,
ch_h_vals,
num_points,
}
}
pub fn single_dir_points(&self, direction: u8) -> Vec<Vec<[f64; 2]>> {
assert!(direction < 3, "Direction must be 0, 1, or 2");
let d_re = (direction * 2) as usize;
let d_im = (direction * 2 + 1) as usize;
self.ch_h_vals
.iter()
.map(|ch| ch.iter().map(|point| [point[d_re], point[d_im]]).collect())
.collect()
}
pub fn double_dir_points(&self, directions: [u8; 2]) -> Vec<Vec<[f64; 4]>> {
assert!(directions[0] < 3, "First Direction must be 0, 1, or 2");
assert!(directions[1] < 3, "Second Direction must be 0, 1, or 2");
assert_ne!(
directions[0], directions[1],
"First and Second Direction cannot be the same value!"
);
let d1_re = (directions[0] * 2) as usize;
let d1_im = (directions[0] * 2 + 1) as usize;
let d2_re = (directions[1] * 2) as usize;
let d2_im = (directions[1] * 2 + 1) as usize;
self.ch_h_vals
.iter()
.map(|ch| {
ch.iter()
.map(|point| [point[d1_re], point[d1_im], point[d2_re], point[d2_im]])
.collect()
})
.collect()
}
pub fn grouped_double_dir_data_points(
&self,
directions: [u8; 2],
grouping_axis: usize,
) -> Vec<Vec<Vec<[f64; 4]>>> {
assert!(directions[0] < 3, "First Direction must be 0, 1, or 2");
assert!(directions[1] < 3, "Second Direction must be 0, 1, or 2");
assert_ne!(
directions[0], directions[1],
"First and Second Direction cannot be the same value!"
);
let d1_re = (directions[0] * 2) as usize;
let d1_im = (directions[0] * 2 + 1) as usize;
let d2_re = (directions[1] * 2) as usize;
let d2_im = (directions[1] * 2 + 1) as usize;
assert!(grouping_axis < 3, "Grouping Axis must be 0, 1, or 2!");
let axis = grouping_axis as usize;
let mut axis_geo_keys: BTreeMap<i32, usize> = BTreeMap::new();
for geo_key in &self.geo_keys {
let axis_key = geo_key[axis];
let num_points = axis_geo_keys.entry(axis_key).or_insert(0);
*num_points += 1;
}
let num_channels = self.ch_h_vals.len();
let num_unique_axis_dims = axis_geo_keys.len();
let mut ch_geo_pts: Vec<Vec<Vec<[f64; 4]>>> = Vec::with_capacity(num_channels);
for ch in 0..num_channels {
ch_geo_pts.push(Vec::with_capacity(num_unique_axis_dims));
for (group_index, (axis_key, num_points)) in axis_geo_keys.iter().enumerate() {
ch_geo_pts[ch].push(Vec::with_capacity(*num_points));
for (h_pt, geo_key) in self.ch_h_vals[ch].iter().zip(&self.geo_keys) {
if geo_key[axis] == *axis_key {
ch_geo_pts[ch][group_index].push([
h_pt[d1_re],
h_pt[d1_im],
h_pt[d2_re],
h_pt[d2_im],
]);
}
}
}
}
ch_geo_pts
}
}
fn gen_geo_key(geo_floats: &[f64; 3]) -> [i32; 3] {
[
(geo_floats[0] * 1000.0) as i32,
(geo_floats[1] * 1000.0) as i32,
(geo_floats[2] * 1000.0) as i32,
]
}