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>,
19 #[serde(default)]
20 pub dark_frame: Option<PathBuf>,
22 #[serde(default)]
23 pub flat_field: Option<PathBuf>,
25 #[serde(default)]
26 pub background: Option<ImageSet>,
28 #[serde(default)]
29 pub mask: Option<ImageSet>,
31 #[serde(default)]
32 pub preprocessing: PreprocessingConfig,
34}
35
36impl MeasurementSpec {
37 pub fn new(frames: Vec<FrameSpec>) -> Self {
39 Self {
40 frames,
41 dark_frame: None,
42 flat_field: None,
43 background: None,
44 mask: None,
45 preprocessing: PreprocessingConfig::default(),
46 }
47 }
48
49 pub fn save(&self, path: impl AsRef<Path>) -> Result<()> {
51 let writer = BufWriter::new(File::create(path)?);
52 serde_json::to_writer_pretty(writer, self)?;
53 Ok(())
54 }
55
56 pub fn load(path: impl AsRef<Path>) -> Result<Self> {
58 let reader = BufReader::new(File::open(path)?);
59 Ok(serde_json::from_reader(reader)?)
60 }
61}
62
63#[derive(Clone, Debug, Serialize, Deserialize)]
64#[serde(deny_unknown_fields)]
65pub struct FrameSpec {
67 pub path: PathBuf,
69 #[serde(default)]
70 pub illumination_index: Option<usize>,
72 #[serde(default = "unit_value")]
73 pub exposure_time: f64,
75 #[serde(default = "unit_value")]
76 pub weight: f64,
78 #[serde(default)]
79 pub label: Option<String>,
81}
82
83impl FrameSpec {
84 pub fn new(path: impl Into<PathBuf>) -> Self {
86 Self {
87 path: path.into(),
88 illumination_index: None,
89 exposure_time: 1.0,
90 weight: 1.0,
91 label: None,
92 }
93 }
94}
95
96#[derive(Clone, Debug, Serialize, Deserialize)]
97#[serde(untagged)]
98pub enum ImageSet {
100 Single(PathBuf),
102 PerFrame(Vec<PathBuf>),
104}
105
106fn unit_value() -> f64 {
107 1.0
108}