fpm_rs/measurements/
manifest.rs1use std::{
2 fs::File,
3 io::{BufReader, BufWriter},
4 path::{Path, PathBuf},
5};
6
7use serde::{Deserialize, Serialize};
8
9use crate::Result;
10
11use super::PreprocessingConfig;
12
13#[derive(Clone, Debug, Serialize, Deserialize)]
14#[serde(deny_unknown_fields)]
15pub struct MeasurementSpec {
17 pub frames: Vec<FrameSpec>,
18 #[serde(default)]
19 pub dark_frame: Option<PathBuf>,
20 #[serde(default)]
21 pub flat_field: Option<PathBuf>,
22 #[serde(default)]
23 pub background: Option<ImageSet>,
24 #[serde(default)]
25 pub mask: Option<ImageSet>,
26 #[serde(default)]
27 pub preprocessing: PreprocessingConfig,
28}
29
30impl MeasurementSpec {
31 pub fn new(frames: Vec<FrameSpec>) -> Self {
32 Self {
33 frames,
34 dark_frame: None,
35 flat_field: None,
36 background: None,
37 mask: None,
38 preprocessing: PreprocessingConfig::default(),
39 }
40 }
41
42 pub fn save(&self, path: impl AsRef<Path>) -> Result<()> {
43 let writer = BufWriter::new(File::create(path)?);
44 serde_json::to_writer_pretty(writer, self)?;
45 Ok(())
46 }
47
48 pub fn load(path: impl AsRef<Path>) -> Result<Self> {
49 let reader = BufReader::new(File::open(path)?);
50 Ok(serde_json::from_reader(reader)?)
51 }
52}
53
54#[derive(Clone, Debug, Serialize, Deserialize)]
55#[serde(deny_unknown_fields)]
56pub struct FrameSpec {
58 pub path: PathBuf,
59 #[serde(default)]
60 pub illumination_index: Option<usize>,
61 #[serde(default = "unit_value")]
62 pub exposure_time: f64,
63 #[serde(default = "unit_value")]
64 pub weight: f64,
65 #[serde(default)]
66 pub label: Option<String>,
67}
68
69impl FrameSpec {
70 pub fn new(path: impl Into<PathBuf>) -> Self {
71 Self {
72 path: path.into(),
73 illumination_index: None,
74 exposure_time: 1.0,
75 weight: 1.0,
76 label: None,
77 }
78 }
79}
80
81#[derive(Clone, Debug, Serialize, Deserialize)]
82#[serde(untagged)]
83pub enum ImageSet {
85 Single(PathBuf),
86 PerFrame(Vec<PathBuf>),
87}
88
89fn unit_value() -> f64 {
90 1.0
91}