cherry_rs/specs/
fields.rsuse anyhow::Result;
use serde::{Deserialize, Serialize};
use crate::core::Float;
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum PupilSampling {
SquareGrid { spacing: Float },
ChiefAndMarginalRays,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub enum FieldSpec {
Angle {
angle: Float,
pupil_sampling: PupilSampling,
},
ObjectHeight {
height: Float,
pupil_sampling: PupilSampling,
},
}
impl PupilSampling {
pub fn validate(&self) -> Result<()> {
match self {
PupilSampling::SquareGrid { spacing } => {
if spacing.is_nan() {
anyhow::bail!("Pupil grid spacing must be a number");
}
if *spacing < 0.0 || *spacing > 1.0 {
anyhow::bail!("Pupil grid spacing must be in the range [0, 1]");
}
}
PupilSampling::ChiefAndMarginalRays => {}
}
Ok(())
}
}
impl Default for PupilSampling {
fn default() -> Self {
Self::SquareGrid { spacing: 0.1 }
}
}
impl FieldSpec {
pub fn validate(&self) -> Result<()> {
match self {
FieldSpec::Angle {
angle,
pupil_sampling,
} => {
if angle.is_nan() {
anyhow::bail!("Field angle must be a number");
}
if *angle < 0.0 || *angle > 90.0 {
anyhow::bail!("Field angle must be in the range [0, 90]");
}
pupil_sampling.validate()?;
}
FieldSpec::ObjectHeight {
height,
pupil_sampling,
} => {
if height.is_nan() {
anyhow::bail!("Field height must be a number");
}
pupil_sampling.validate()?;
}
}
Ok(())
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_pupil_sampling_validate() {
let square_grid = PupilSampling::SquareGrid { spacing: 0.1 };
assert!(square_grid.validate().is_ok());
let square_grid = PupilSampling::SquareGrid { spacing: 1.1 };
assert!(square_grid.validate().is_err());
let square_grid = PupilSampling::SquareGrid { spacing: -0.1 };
assert!(square_grid.validate().is_err());
let square_grid = PupilSampling::SquareGrid {
spacing: Float::NAN,
};
assert!(square_grid.validate().is_err());
}
#[test]
fn test_field_spec_validate() {
let angle = FieldSpec::Angle {
angle: 45.0,
pupil_sampling: PupilSampling::SquareGrid { spacing: 0.1 },
};
assert!(angle.validate().is_ok());
let angle = FieldSpec::Angle {
angle: 95.0,
pupil_sampling: PupilSampling::SquareGrid { spacing: 0.1 },
};
assert!(angle.validate().is_err());
let angle = FieldSpec::Angle {
angle: -5.0,
pupil_sampling: PupilSampling::SquareGrid { spacing: 0.1 },
};
assert!(angle.validate().is_err());
let angle = FieldSpec::Angle {
angle: 45.0,
pupil_sampling: PupilSampling::SquareGrid { spacing: 1.1 },
};
assert!(angle.validate().is_err());
let angle = FieldSpec::Angle {
angle: 45.0,
pupil_sampling: PupilSampling::SquareGrid { spacing: -0.1 },
};
assert!(angle.validate().is_err());
let angle = FieldSpec::Angle {
angle: 45.0,
pupil_sampling: PupilSampling::SquareGrid {
spacing: Float::NAN,
},
};
assert!(angle.validate().is_err());
let height = FieldSpec::ObjectHeight {
height: 0.1,
pupil_sampling: PupilSampling::SquareGrid { spacing: 0.1 },
};
assert!(height.validate().is_ok());
let height = FieldSpec::ObjectHeight {
height: 0.1,
pupil_sampling: PupilSampling::SquareGrid { spacing: 1.1 },
};
assert!(height.validate().is_err());
}
}