Skip to main content

fpm_rs/reconstruction/
problem.rs

1use crate::{Result, error::Error, measurements::MeasurementRead, model::ImagePlaneModel};
2
3#[derive(Clone, Debug)]
4pub struct ReconstructionProblem<M> {
5    pub measurements: M,
6    pub model: ImagePlaneModel,
7    pub name: Option<String>,
8}
9
10impl<M: MeasurementRead> ReconstructionProblem<M> {
11    pub fn new(measurements: M, model: ImagePlaneModel) -> Result<Self> {
12        let problem = Self {
13            measurements,
14            model,
15            name: None,
16        };
17        problem.validate()?;
18        Ok(problem)
19    }
20
21    pub fn named(mut self, name: impl Into<String>) -> Self {
22        self.name = Some(name.into());
23        self
24    }
25
26    pub fn validate(&self) -> Result<()> {
27        self.model.validate()?;
28        self.measurements.validate()?;
29        if self.measurements.frame_count() != self.model.frame_count() {
30            return Err(Error::InvalidModel(format!(
31                "{} measurement frames but {} model frames",
32                self.measurements.frame_count(),
33                self.model.frame_count()
34            )));
35        }
36        if self.measurements.image_shape() != self.model.image_shape {
37            return Err(Error::InvalidShape(format!(
38                "measurement shape {:?} differs from model image shape {:?}",
39                self.measurements.image_shape(),
40                self.model.image_shape
41            )));
42        }
43        let mut positive_weight_frames = 0;
44        for frame in 0..self.measurements.frame_count() {
45            if self.measurements.frame_weight(frame)? > 0.0 {
46                positive_weight_frames += 1;
47            }
48            if self.measurements.frame_weight(frame)? > 0.0
49                && self
50                    .measurements
51                    .frame_mask(frame)?
52                    .is_some_and(|mask| mask.iter().all(|&value| value == 0))
53            {
54                return Err(Error::InvalidMeasurements(format!(
55                    "positive-weight frame {frame} has no unmasked pixels"
56                )));
57            }
58        }
59        if positive_weight_frames == 0 {
60            return Err(Error::InvalidMeasurements(
61                "at least one frame must have positive weight".into(),
62            ));
63        }
64        Ok(())
65    }
66}