1use crate::header::Header;
2
3#[derive(Debug, Clone)]
10pub struct Group {
11 parameters: Vec<f64>,
12 names: Vec<String>,
13 data: Vec<f64>,
14}
15
16impl Group {
17 pub(crate) fn new(parameters: Vec<f64>, names: Vec<String>, data: Vec<f64>) -> Self {
18 Self {
19 parameters,
20 names,
21 data,
22 }
23 }
24
25 pub fn parameters(&self) -> &[f64] {
30 &self.parameters
31 }
32
33 pub fn parameter(&self, name: &str) -> Option<f64> {
39 let mut total = None;
40
41 for (index, parameter_name) in self.names.iter().enumerate() {
42 if parameter_name == name {
43 total = Some(total.unwrap_or(0.0) + self.parameters.get(index).copied()?);
44 }
45 }
46
47 total
48 }
49
50 pub fn parameter_names(&self) -> &[String] {
52 &self.names
53 }
54
55 pub fn data(&self) -> &[f64] {
57 &self.data
58 }
59}
60
61pub(crate) fn decode_group(header: &Header, bytes: &[u8]) -> Option<Group> {
63 let bitpix = header.bitpix()?;
64 let width = bitpix.byte_size();
65
66 let count = header.pcount().unwrap_or(0).max(0) as usize;
67 let zero = header.bzero_or_default();
68 let scale = header.bscale_or_default();
69
70 let mut parameters = Vec::with_capacity(count);
71 let mut names = Vec::with_capacity(count);
72
73 for index in 0..count {
74 let raw = bitpix.read_be(bytes.get(index * width..)?)?;
75
76 let parameter_scale = header.parameter_scaling_factor(index).unwrap_or(1.0);
78 let parameter_zero = header.parameter_scaling_zero_point(index).unwrap_or(0.0);
79
80 parameters.push(parameter_zero + parameter_scale * raw);
81 names.push(header.parameter_type(index).unwrap_or_default().to_string());
82 }
83
84 let array = bytes.get(count * width..)?;
85 let data = array
86 .chunks_exact(width)
87 .filter_map(|raw| bitpix.read_be(raw))
88 .map(|raw| zero + scale * raw)
89 .collect();
90
91 Some(Group::new(parameters, names, data))
92}