Newer
Older
analyzer::AnalyzerType,
lightdata::{DataEnergy, LightData},
///
/// ## Optical Ports
/// - Inputs
/// - `input1`
/// - `input2`
/// - Outputs
/// - `out1_trans1_refl2`
/// - `out2_trans2_refl1`
///
/// ## Properties
/// - `name`
/// - `ratio`
/// - `inverted`
fn create_default_props() -> Properties {
let mut props = Properties::default();
props.set("name", "beam splitter".into());
props.set("ratio", 0.5.into());
props.set("inverted", false.into());
impl BeamSplitter {
/// Creates a new [`BeamSplitter`] with a given splitting ratio.
/// ## Errors
/// This function returns an [`OpossumError::Other`] if the splitting ratio is outside the closed interval
/// [0.0..1.0].
} else {
Err(OpossumError::Other(
"splitting ratio must be within (0.0..1.0)".into(),
/// Returns the splitting ratio of this [`BeamSplitter`].
if let Some(value) = self.props.get("ratio") {
if let Proptype::F64(value) = value.prop {
return value;
}
}
panic!("wrong data format")
/// Sets the splitting ratio of this [`BeamSplitter`].
/// ## Errors
/// This function returns an [`OpossumError::Other`] if the splitting ratio is outside the closed interval
/// [0.0..1.0].
Ok(())
} else {
Err(OpossumError::Other(
"splitting ration must be within (0.0..1.0)".into(),
))
}
fn analyze_energy(&mut self, incoming_data: LightResult) -> OpmResult<LightResult> {

Udo Eisenbarth
committed
let (in1, in2) = if !self.inverted() {
(incoming_data.get("input1"), incoming_data.get("input2"))
} else {
(
incoming_data.get("out1_trans1_refl2"),
incoming_data.get("out2_trans2_refl1"),
)
};
let mut out1_1_spectrum: Option<Spectrum> = None;
let mut out1_2_spectrum: Option<Spectrum> = None;
let mut out2_1_spectrum: Option<Spectrum> = None;
let mut out2_2_spectrum: Option<Spectrum> = None;
if let Some(Some(in1)) = in1 {
match in1 {
LightData::Energy(e) => {
let mut s = e.spectrum.clone();
s.scale_vertical(self.ratio()).unwrap();
out1_1_spectrum = Some(s);
s.scale_vertical(1.0 - self.ratio()).unwrap();
_ => {
return Err(OpossumError::Analysis(
"expected DataEnergy value at input port".into(),
))
}
if let Some(Some(in2)) = in2 {
match in2 {
LightData::Energy(e) => {
let mut s = e.spectrum.clone();
s.scale_vertical(self.ratio()).unwrap();
out2_1_spectrum = Some(s);
s.scale_vertical(1.0 - self.ratio()).unwrap();
out2_2_spectrum = Some(s);
}
_ => {
return Err(OpossumError::Analysis(
"expected DataEnergy value at input port".into(),
))
}
let out1_spec = merge_spectra(out1_1_spectrum, out2_2_spectrum);
let out2_spec = merge_spectra(out1_2_spectrum, out2_1_spectrum);
let mut out1_data: Option<LightData> = None;
let mut out2_data: Option<LightData> = None;
if let Some(out1_spec) = out1_spec {
out1_data = Some(LightData::Energy(DataEnergy {
spectrum: out1_spec,
}))
if let Some(out2_spec) = out2_spec {
out2_data = Some(LightData::Energy(DataEnergy {
spectrum: out2_spec,
}))

Udo Eisenbarth
committed
if !self.inverted() {
Ok(HashMap::from([
("out1_trans1_refl2".into(), out1_data),
("out2_trans2_refl1".into(), out2_data),
]))
} else {
Ok(HashMap::from([
("input1".into(), out1_data),
("input2".into(), out2_data),
]))
}
if let Proptype::String(name) = &self.props.get("name").unwrap().prop {
fn ports(&self) -> OpticPorts {
let mut ports = OpticPorts::new();
ports.add_input("input1").unwrap();
ports.add_input("input2").unwrap();
ports.add_output("out1_trans1_refl2").unwrap();
ports.add_output("out2_trans2_refl1").unwrap();

Udo Eisenbarth
committed
if self.properties().get_bool("inverted").unwrap().unwrap() {
ports.set_inverted(true)
}
fn analyze(
&mut self,
incoming_data: LightResult,
analyzer_type: &AnalyzerType,
match analyzer_type {
AnalyzerType::Energy => self.analyze_energy(incoming_data),
_ => Err(OpossumError::Analysis(
"analysis type not yet implemented".into(),
)),
fn properties(&self) -> &Properties {
&self.props
fn set_property(&mut self, name: &str, prop: Property) -> OpmResult<()> {
if self.props.set(name, prop).is_none() {
Err(OpossumError::Other("property not defined".into()))
} else {
Ok(())
}
}

Udo Eisenbarth
committed
fn inverted(&self) -> bool {
self.properties().get_bool("inverted").unwrap().unwrap()
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn default() {
let node = BeamSplitter::default();
assert_eq!(node.ratio(), 0.5);
assert_eq!(node.name(), "beam splitter");
assert_eq!(node.node_type(), "beam splitter");
assert_eq!(node.is_detector(), false);
assert_eq!(node.inverted(), false);
assert_eq!(node.node_color(), "lightpink");
assert!(node.as_group().is_err());
}
#[test]
let splitter = BeamSplitter::new(0.6);
assert_eq!(splitter.unwrap().ratio(), 0.6);
assert!(BeamSplitter::new(-0.01).is_err());
assert!(BeamSplitter::new(1.01).is_err());
}
#[test]
fn ratio() {
assert_eq!(splitter.ratio(), 0.5);
}
#[test]
fn set_ratio() {
assert!(splitter.set_ratio(1.0).is_ok());
assert_eq!(splitter.ratio(), 1.0);
assert!(splitter.set_ratio(-0.1).is_err());
assert!(splitter.set_ratio(1.1).is_err());
}