1mod _impl;
2mod main_file;
3pub mod tallies;
4use crate::error::ApiError;
5use _impl::get_probe_size;
6pub use _impl::{
7 get_n_export_real, make_histogram, read_avg_model_properties, read_model_mass,
8 read_model_properties, read_spatial_model_properties,
9};
10pub use main_file::MainResult;
11use ndarray::{s, Array1, Array2, ArrayView1, ArrayView2, ArrayView3};
12use std::path::PathBuf;
13
14trait ResultGroup<T> {
15 fn read_g(&self) -> hdf5::Result<T>;
16}
17
18#[derive(Debug)]
19pub struct Dim(pub usize, pub usize);
20
21#[derive(Debug)]
22pub enum Weight {
23 Single(f64), Multiple(Vec<f64>), }
26
27#[derive(Debug)]
28pub struct Results {
29 pub main: MainResult,
30 pub files: Vec<String>,
31 pub total_particle_repetition: Array2<f64>,
32 pub property_name: Vec<String>,
33}
34
35impl Results {
36 pub fn new(fp: &str, root: &str, folder: &str) -> Result<Self, ApiError> {
37 match MainResult::read(fp) {
38 Ok(main) => {
39 let files: Vec<String> = (0..main.misc.n_rank)
40 .map(|i| format!("{}/{}/{}_partial_{}.h5", root, folder, folder, i))
41 .collect();
42
43 let nt = main.records.time.len();
44 let shape = (nt, main.records.dim.0);
45 let mut total_particle_repetition: Array2<f64> = Array2::zeros(shape);
46 for i_f in &files {
47 let n_p = _impl::read_number_particle(i_f)?;
48 total_particle_repetition =
49 total_particle_repetition + Array2::from_shape_vec(shape, n_p).unwrap();
50 }
51 let property_name = Self::get_property_name(&files);
52 Ok(Results {
53 main,
54 files,
55 total_particle_repetition,
56 property_name,
57 })
58 }
59 Err(hdf5_error) => Err(ApiError::Io(hdf5_error)),
60 }
61 }
62
63 fn get_property_name(files: &[String]) -> Vec<String> {
64 if let Ok(file) = hdf5::File::open(files[0].clone()) {
65 if let Ok(group) = file.group("biological_model/0") {
66 let dataset_names: Vec<String> = group
67 .datasets()
68 .unwrap()
69 .into_iter()
70 .map(|d| {
71 PathBuf::from(d.name())
72 .file_name()
73 .and_then(|name| name.to_str())
74 .unwrap_or("")
75 .to_string()
76 }) .collect();
78 return dataset_names;
79
80 }
84 }
85 vec![] }
87
88 pub fn get_files(&self) -> &[String] {
89 &self.files
90 }
91}
92
93pub fn f_get_probes(files: &[String]) -> Result<Array1<f64>, ApiError> {
94 let total_size = get_probe_size(files)?;
95 let mut probe = Array1::zeros(total_size);
96 let mut offset = 0;
97
98 for filename in files.iter() {
99 let file = hdf5::File::open(filename)?;
100 let dataset = file.dataset("probes")?;
101 let temp_array: Vec<f64> = dataset.read_raw::<f64>()?;
102 let tmp_array = match ArrayView1::from_shape(temp_array.len(), &temp_array) {
103 Ok(view) => view,
104 Err(_) => return Err(ApiError::ShapeError),
105 };
106 probe
107 .slice_mut(s![offset..offset + temp_array.len()])
108 .assign(&tmp_array);
109 offset += temp_array.len();
110 }
111
112 Ok(probe)
113}
114
115pub fn vec_to_array_view2(vec: &[f64], nr: usize, nc: usize) -> ArrayView2<'_, f64> {
116 assert_eq!(vec.len(), nr * nc, "Vector size must match dimensions.");
117 ArrayView2::from_shape((nr, nc), vec).expect("Failed to create ArrayView2")
118}
119
120pub fn vec_to_array_view3<'a>(vec: &'a [f64], dim: &'a Dim, nt: usize) -> ArrayView3<'a, f64> {
121 assert_eq!(
122 vec.len(),
123 nt * dim.0 * dim.1,
124 "Vector size must match dimensions."
125 );
126 ArrayView3::from_shape((nt, dim.0, dim.1), vec).expect("Failed to create ArrayView2")
127}
128
129#[cfg(test)]
130mod tests {
131 use super::*;
132 use ndarray::{array, Array3};
133
134 #[test]
135 fn test_vec_to_array_view2_valid() {
136 let vec = vec![1.0, 2.0, 3.0, 4.0]; let nr = 2;
138 let nc = 2;
139
140 let view = vec_to_array_view2(&vec, nr, nc);
141
142 assert_eq!(view.shape(), &[2, 2]);
143 assert_eq!(view, array![[1.0, 2.0], [3.0, 4.0]]);
144 }
145
146 #[test]
147 #[should_panic(expected = "Vector size must match dimensions.")]
148 fn test_vec_to_array_view2_invalid_size() {
149 let vec = vec![1.0, 2.0, 3.0]; let nr = 2;
151 let nc = 2;
152
153 vec_to_array_view2(&vec, nr, nc);
154 }
155
156 #[test]
157 #[should_panic]
158 fn test_vec_to_array_view2_empty_vector() {
159 let vec: Vec<f64> = vec![];
160 let nr = 2;
161 let nc = 2;
162
163 vec_to_array_view2(&vec, nr, nc);
164 }
165 #[test]
166 fn test_vec_to_array_view3() {
167 let vec = vec![1.0; 6]; let dim = &Dim(2, 3);
169 let nt = 1;
170 let vec_copy = vec.clone();
171 let array_view = vec_to_array_view3(&vec, dim, nt);
172
173 let expected_array = Array3::from_shape_vec((nt, dim.0, dim.1), vec_copy)
174 .expect("Failed to create expected Array3");
175 assert_eq!(array_view, expected_array.view());
176 }
177
178 #[test]
179 #[should_panic]
180 fn test_vec_to_array_view3_size_mismatch() {
181 let vec = vec![1.0, 2.0, 3.0];
182 let dim = &Dim(2, 3);
183 let nt = 1;
184
185 let _ = vec_to_array_view3(&vec, dim, nt);
186 }
187
188 #[test]
189 #[should_panic]
190 fn test_vec_to_array_view3_invalid_size() {
191 let vec = vec![1.0, 2.0, 3.0]; let dim = Dim(1, 2);
193 let nt = 1;
194
195 vec_to_array_view3(&vec, &dim, nt);
196 }
197
198 #[test]
199 #[should_panic]
200 fn test_vec_to_array_view3_empty_vector() {
201 let vec: Vec<f64> = vec![];
202 let dim = Dim(1, 2);
203 let nt = 1;
204
205 vec_to_array_view3(&vec, &dim, nt);
206 }
207}