diff --git a/opossum/examples/apodization.rs b/opossum/examples/apodization.rs new file mode 100644 index 0000000000000000000000000000000000000000..707be419b2e68731341ec11c31fb56b6e8a2b3b0 --- /dev/null +++ b/opossum/examples/apodization.rs @@ -0,0 +1,39 @@ +use std::path::Path; + +use opossum::{ + analyzers::{AnalyzerType, RayTraceConfig}, + aperture::{Aperture, RectangleConfig}, + error::OpmResult, + joule, millimeter, + nodes::{round_collimated_ray_source, Dummy, NodeGroup, SpotDiagram}, + optic_node::{Alignable, OpticNode}, + optic_ports::PortType, + OpmDocument, +}; + +fn main() -> OpmResult<()> { + let mut scenery = NodeGroup::default(); + + let i_src = scenery.add_node(&round_collimated_ray_source( + millimeter!(20.0), + joule!(1.0), + 10, + )?)?; + + let mut dummy = Dummy::default(); + let rect_config = + RectangleConfig::new(millimeter!(15.), millimeter!(15.), millimeter!(0.0, 0.0))?; + let aperture = Aperture::BinaryRectangle(rect_config); + dummy.set_aperture(&PortType::Input, "front", &aperture)?; + let dummy = dummy.with_decenter(millimeter!(-5.0, 5.0, 0.0))?; + + let i_d = scenery.add_node(&dummy)?; + let i_sd = scenery.add_node(&SpotDiagram::default())?; + + scenery.connect_nodes(i_src, "out1", i_d, "front", millimeter!(50.0))?; + scenery.connect_nodes(i_d, "rear", i_sd, "in1", millimeter!(50.0))?; + + let mut doc = OpmDocument::new(scenery); + doc.add_analyzer(AnalyzerType::RayTrace(RayTraceConfig::default())); + doc.save_to_file(Path::new("./opossum/playground/apodization.opm")) +} diff --git a/opossum/examples/rays.rs b/opossum/examples/rays.rs deleted file mode 100644 index cc1a15445d22f55e9906092d4d41c4bdf7fc8207..0000000000000000000000000000000000000000 --- a/opossum/examples/rays.rs +++ /dev/null @@ -1,12 +0,0 @@ -use opossum::{ - error::OpmResult, joule, millimeter, nanometer, position_distributions::Random, rays::Rays, -}; - -fn main() -> OpmResult<()> { - let _rays = Rays::new_uniform_collimated( - nanometer!(1054.0), - joule!(1.0), - &Random::new(millimeter!(1.0), millimeter!(1.0), 200)?, - )?; - Ok(()) -} diff --git a/opossum/src/analyzers/raytrace.rs b/opossum/src/analyzers/raytrace.rs index 9935e5086dcadace61a9961e7e655f85716dbff0..e5eca4b199d50900e6e51f94f01c368e9355832d 100644 --- a/opossum/src/analyzers/raytrace.rs +++ b/opossum/src/analyzers/raytrace.rs @@ -94,10 +94,15 @@ pub trait AnalysisRayTrace: OpticNode + Surface { port_name: &str, ) -> OpmResult<()> { let uuid = *self.node_attr().uuid(); + let Some(iso) = &self.effective_iso() else { + return Err(OpossumError::Analysis( + "surface has no isometry defined".into(), + )); + }; if backward { for rays in &mut *rays_bundle { if let Some(aperture) = self.ports().aperture(&PortType::Input, port_name) { - rays.apodize(aperture)?; + rays.apodize(aperture, iso)?; if let AnalyzerType::RayTrace(ref config) = analyzer_type { rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; } @@ -120,7 +125,7 @@ pub trait AnalysisRayTrace: OpticNode + Surface { } else { for rays in &mut *rays_bundle { if let Some(aperture) = self.ports().aperture(&PortType::Input, port_name) { - rays.apodize(aperture)?; + rays.apodize(aperture, &self.effective_iso().unwrap())?; if let AnalyzerType::RayTrace(ref config) = analyzer_type { rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; } @@ -154,6 +159,11 @@ pub trait AnalysisRayTrace: OpticNode + Surface { port_name: &str, ) -> OpmResult<()> { let uuid: uuid::Uuid = *self.node_attr().uuid(); + let Some(iso) = &self.effective_iso() else { + return Err(OpossumError::Analysis( + "surface has no isometry defined".into(), + )); + }; let surf = self.get_surface_mut(port_name); if backward { for rays in &mut *rays_bundle { @@ -171,7 +181,7 @@ pub trait AnalysisRayTrace: OpticNode + Surface { } for rays in &mut *rays_bundle { if let Some(aperture) = self.ports().aperture(&PortType::Output, port_name) { - rays.apodize(aperture)?; + rays.apodize(aperture, iso)?; if let AnalyzerType::RayTrace(config) = analyzer_type { rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; } @@ -193,7 +203,7 @@ pub trait AnalysisRayTrace: OpticNode + Surface { } for rays in &mut *rays_bundle { if let Some(aperture) = self.ports().aperture(&PortType::Output, port_name) { - rays.apodize(aperture)?; + rays.apodize(aperture, iso)?; if let AnalyzerType::RayTrace(config) = analyzer_type { rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; } diff --git a/opossum/src/nodes/beam_splitter/mod.rs b/opossum/src/nodes/beam_splitter/mod.rs index 736be84b9284ea33d2468cfb4e30767189fc6ee4..6a34d1932f6124d790ad84fb6beb12c94cff2f3e 100644 --- a/opossum/src/nodes/beam_splitter/mod.rs +++ b/opossum/src/nodes/beam_splitter/mod.rs @@ -199,19 +199,20 @@ impl BeamSplitter { if let Some(iso) = self.effective_iso() { let mut plane = OpticalSurface::new(Box::new(Plane::new(&iso))); rays.refract_on_surface(&mut plane, None)?; + if let Some(aperture) = self.ports().aperture(&PortType::Input, "input1") { + rays.apodize(aperture, &iso)?; + if let AnalyzerType::RayTrace(config) = analyzer_type { + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; } else { return Err(OpossumError::Analysis( "no location for surface defined. Aborting".into(), )); } - if let Some(aperture) = self.ports().aperture(&PortType::Input, "input1") { - rays.apodize(aperture)?; - if let AnalyzerType::RayTrace(config) = analyzer_type { - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; + let split_rays = rays.split(&splitting_config.value)?; (rays, split_rays) } @@ -228,22 +229,23 @@ impl BeamSplitter { match input2 { LightData::Geometric(r) => { let mut rays = r.clone(); - if let Some(iso) = self.effective_iso() { - let mut plane = OpticalSurface::new(Box::new(Plane::new(&iso))); - rays.refract_on_surface(&mut plane, None)?; - } else { + let Some(iso) = self.effective_iso() else { return Err(OpossumError::Analysis( "no location for surface defined. Aborting".into(), )); - } + }; + + let mut plane = OpticalSurface::new(Box::new(Plane::new(&iso))); + rays.refract_on_surface(&mut plane, None)?; if let Some(aperture) = self.ports().aperture(&PortType::Input, "input2") { - rays.apodize(aperture)?; + rays.apodize(aperture, &iso)?; if let AnalyzerType::RayTrace(config) = analyzer_type { rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; } } else { return Err(OpossumError::OpticPort("input aperture not found".into())); }; + let split_rays = rays.split(&splitting_config.value)?; (rays, split_rays) } @@ -258,11 +260,16 @@ impl BeamSplitter { }; in_ray1.merge(&split2); in_ray2.merge(&split1); + let Some(iso) = self.effective_iso() else { + return Err(OpossumError::Analysis( + "no location for surface defined. Aborting".into(), + )); + }; if let Some(aperture) = self .ports() .aperture(&PortType::Output, "out1_trans1_refl2") { - in_ray1.apodize(aperture)?; + in_ray1.apodize(aperture, &iso)?; if let AnalyzerType::RayTrace(config) = analyzer_type { in_ray1.invalidate_by_threshold_energy(config.min_energy_per_ray())?; } @@ -273,7 +280,7 @@ impl BeamSplitter { .ports() .aperture(&PortType::Output, "out2_trans2_refl1") { - in_ray2.apodize(aperture)?; + in_ray2.apodize(aperture, &iso)?; if let AnalyzerType::RayTrace(config) = analyzer_type { in_ray2.invalidate_by_threshold_energy(config.min_energy_per_ray())?; } diff --git a/opossum/src/nodes/detector.rs b/opossum/src/nodes/detector.rs index 5a3a2123d649fc684c81e9a6cf93eb51276d0303..c45b833c06a8d61580a38783b779e695f1566264 100644 --- a/opossum/src/nodes/detector.rs +++ b/opossum/src/nodes/detector.rs @@ -132,27 +132,27 @@ impl AnalysisRayTrace for Detector { if let Some(iso) = self.effective_iso() { self.surface.set_isometry(&iso); rays.refract_on_surface(&mut self.surface, None)?; + if let Some(aperture) = self.ports().aperture(&PortType::Input, in_port) { + let rays_apodized = rays.apodize(aperture, &iso)?; + if rays_apodized { + warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); + } + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; + self.light_data = Some(LightData::Geometric(rays.clone())); + if let Some(aperture) = self.ports().aperture(&PortType::Output, out_port) { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; } else { return Err(OpossumError::Analysis( "no location for surface defined. Aborting".into(), )); } - if let Some(aperture) = self.ports().aperture(&PortType::Input, in_port) { - let rays_apodized = rays.apodize(aperture)?; - if rays_apodized { - warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); - } - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; - self.light_data = Some(LightData::Geometric(rays.clone())); - if let Some(aperture) = self.ports().aperture(&PortType::Output, out_port) { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; Ok(LightResult::from([( out_port.into(), LightData::Geometric(rays), diff --git a/opossum/src/nodes/dummy.rs b/opossum/src/nodes/dummy.rs index 1ad3ee5c6e16e0920d200ac5795ce841e7308cc3..e5a4cf8cb2bcb8ec01a48679f807fbabaa804ce8 100644 --- a/opossum/src/nodes/dummy.rs +++ b/opossum/src/nodes/dummy.rs @@ -9,7 +9,7 @@ use crate::{ error::{OpmResult, OpossumError}, light_result::LightResult, lightdata::LightData, - optic_node::OpticNode, + optic_node::{Alignable, OpticNode}, optic_ports::{OpticPorts, PortType}, surface::{OpticalSurface, Plane, Surface}, utils::geom_transformation::Isometry, @@ -103,23 +103,24 @@ impl AnalysisRayTrace for Dummy { if let Some(iso) = self.effective_iso() { self.surface.set_isometry(&iso); rays.refract_on_surface(&mut self.surface, None)?; + if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; + if let Some(aperture) = self.ports().aperture(&PortType::Output, outport) { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("output aperture not found".into())); + }; } else { return Err(OpossumError::Analysis( "no location for surface defined. Aborting".into(), )); } - if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; - if let Some(aperture) = self.ports().aperture(&PortType::Output, outport) { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; + Ok(LightResult::from([( outport.into(), LightData::Geometric(rays), @@ -142,6 +143,7 @@ impl OpticNode for Dummy { } } +impl Alignable for Dummy {} impl Dottable for Dummy {} #[cfg(test)] diff --git a/opossum/src/nodes/energy_meter.rs b/opossum/src/nodes/energy_meter.rs index 13df2d6d6d338be6166c4bfc6ab6db7a91326bfa..54dafa482c63dd6ad3e24cc9f3478609656fc92d 100644 --- a/opossum/src/nodes/energy_meter.rs +++ b/opossum/src/nodes/energy_meter.rs @@ -251,28 +251,28 @@ impl AnalysisRayTrace for EnergyMeter { if let Some(iso) = self.effective_iso() { self.surface.set_isometry(&iso); rays.refract_on_surface(&mut self.surface, None)?; + if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { + let rays_apodized = rays.apodize(aperture, &iso)?; + if rays_apodized { + warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); + self.apodization_warning = true; + } + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; + self.light_data = Some(LightData::Geometric(rays.clone())); + if let Some(aperture) = self.ports().aperture(&PortType::Output, outport) { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("output aperture not found".into())); + }; } else { return Err(OpossumError::Analysis( "no location for surface defined. Aborting".into(), )); } - if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { - let rays_apodized = rays.apodize(aperture)?; - if rays_apodized { - warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); - self.apodization_warning = true; - } - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; - self.light_data = Some(LightData::Geometric(rays.clone())); - if let Some(aperture) = self.ports().aperture(&PortType::Output, outport) { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("output aperture not found".into())); - }; Ok(LightResult::from([( outport.into(), LightData::Geometric(rays), diff --git a/opossum/src/nodes/fluence_detector.rs b/opossum/src/nodes/fluence_detector.rs index 4048710359fa09c01caf476d7b50c8359a7a510d..ff09075b6ec95075f96bc01fb9dab4375ac16648 100644 --- a/opossum/src/nodes/fluence_detector.rs +++ b/opossum/src/nodes/fluence_detector.rs @@ -242,28 +242,28 @@ impl AnalysisRayTrace for FluenceDetector { if let Some(iso) = self.effective_iso() { self.surface.set_isometry(&iso); rays.refract_on_surface(&mut self.surface, None)?; + if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { + let rays_apodized = rays.apodize(aperture, &iso)?; + if rays_apodized { + warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); + self.apodization_warning = true; + } + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; + self.light_data = Some(LightData::Geometric(rays.clone())); + if let Some(aperture) = self.ports().aperture(&PortType::Output, outport) { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("output aperture not found".into())); + }; } else { return Err(OpossumError::Analysis( "no location for surface defined. Aborting".into(), )); } - if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { - let rays_apodized = rays.apodize(aperture)?; - if rays_apodized { - warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); - self.apodization_warning = true; - } - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; - self.light_data = Some(LightData::Geometric(rays.clone())); - if let Some(aperture) = self.ports().aperture(&PortType::Output, outport) { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("output aperture not found".into())); - }; Ok(LightResult::from([( outport.into(), LightData::Geometric(rays), diff --git a/opossum/src/nodes/ideal_filter.rs b/opossum/src/nodes/ideal_filter.rs index e4a598f8bfff1c94eba91a551c83c14e5275c780..e766db11367f63174aad42524346c81e4936bfef 100644 --- a/opossum/src/nodes/ideal_filter.rs +++ b/opossum/src/nodes/ideal_filter.rs @@ -242,24 +242,24 @@ impl AnalysisRayTrace for IdealFilter { .clone(), ); rays.refract_on_surface(&mut self.surface, None)?; + rays.filter_energy(&self.filter_type())?; + if let Some(aperture) = self.ports().aperture(&PortType::Input, in_port) { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; + if let Some(aperture) = self.ports().aperture(&PortType::Output, out_port) { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("output aperture not found".into())); + }; } else { return Err(OpossumError::Analysis( "no location for surface defined. Aborting".into(), )); } - rays.filter_energy(&self.filter_type())?; - if let Some(aperture) = self.ports().aperture(&PortType::Input, in_port) { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; - if let Some(aperture) = self.ports().aperture(&PortType::Output, out_port) { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("output aperture not found".into())); - }; let light_data = LightData::Geometric(rays); Ok(LightResult::from([(out_port.into(), light_data)])) } diff --git a/opossum/src/nodes/paraxial_surface.rs b/opossum/src/nodes/paraxial_surface.rs index 4b3287d432d08b90c71dcab7cfc8b782e84a97f8..987f461f7f9e1061e27fdd4e0103261ce7e35b37 100644 --- a/opossum/src/nodes/paraxial_surface.rs +++ b/opossum/src/nodes/paraxial_surface.rs @@ -148,23 +148,23 @@ impl AnalysisRayTrace for ParaxialSurface { None, )?; rays.refract_paraxial(*focal_length, &iso)?; + if let Some(aperture) = self.ports().aperture(&PortType::Input, in_port) { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; + if let Some(aperture) = self.ports().aperture(&PortType::Output, out_port) { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("output aperture not found".into())); + }; } else { return Err(OpossumError::Analysis( "no location for surface defined. Aborting".into(), )); } - if let Some(aperture) = self.ports().aperture(&PortType::Input, in_port) { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; - if let Some(aperture) = self.ports().aperture(&PortType::Output, out_port) { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("output aperture not found".into())); - }; let mut light_result = LightResult::default(); light_result.insert(out_port.into(), LightData::Geometric(rays)); Ok(light_result) diff --git a/opossum/src/nodes/ray_propagation_visualizer.rs b/opossum/src/nodes/ray_propagation_visualizer.rs index cef8299d54bce72726b2e3ce1b9b7f7a9f781d3a..f7ef9ccabd5d4b6f2a709deb3de0653e62ccccd1 100644 --- a/opossum/src/nodes/ray_propagation_visualizer.rs +++ b/opossum/src/nodes/ray_propagation_visualizer.rs @@ -213,31 +213,31 @@ impl AnalysisRayTrace for RayPropagationVisualizer { if let Some(iso) = self.effective_iso() { self.surface.set_isometry(&iso); rays.refract_on_surface(&mut self.surface, None)?; + if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { + let rays_apodized = rays.apodize(aperture, &iso)?; + if rays_apodized { + warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); + self.apodization_warning = true; + } + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; + self.light_data = Some(LightData::Geometric(rays.clone())); + if let Some(aperture) = self.ports().aperture(&PortType::Output, outport) { + let rays_apodized = rays.apodize(aperture, &iso)?; + if rays_apodized { + warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); + } + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("output aperture not found".into())); + }; } else { return Err(OpossumError::Analysis( "no location for surface defined. Aborting".into(), )); } - if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { - let rays_apodized = rays.apodize(aperture)?; - if rays_apodized { - warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); - self.apodization_warning = true; - } - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; - self.light_data = Some(LightData::Geometric(rays.clone())); - if let Some(aperture) = self.ports().aperture(&PortType::Output, outport) { - let rays_apodized = rays.apodize(aperture)?; - if rays_apodized { - warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); - } - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("output aperture not found".into())); - }; Ok(LightResult::from([( outport.into(), LightData::Geometric(rays), diff --git a/opossum/src/nodes/reflective_grating.rs b/opossum/src/nodes/reflective_grating.rs index 4579db7695ac367edd0fe6d5e5cdb3ebb56095a1..4cd18960b416d3c1448bd27db7e2dfd197b8f913 100644 --- a/opossum/src/nodes/reflective_grating.rs +++ b/opossum/src/nodes/reflective_grating.rs @@ -220,7 +220,7 @@ impl AnalysisRayTrace for ReflectiveGrating { )?; if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { - diffracted_rays.apodize(aperture)?; + diffracted_rays.apodize(aperture, &iso)?; diffracted_rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; diffracted_rays } else { diff --git a/opossum/src/nodes/source.rs b/opossum/src/nodes/source.rs index af85f8da9c0cece41cb8892595121fc294f6d701..d35ccf5af5dae5d14f3c6311af3321692c066630 100644 --- a/opossum/src/nodes/source.rs +++ b/opossum/src/nodes/source.rs @@ -210,15 +210,17 @@ impl AnalysisRayTrace for Source { if let LightData::Geometric(rays) = &mut data { if let Some(iso) = self.effective_iso() { *rays = rays.transformed_rays(&iso); - } - // consider aperture only if not inverted (there is only an output port) - if !self.inverted() { - if let Some(aperture) = self.ports().aperture(&PortType::Output, "out1") { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; + // consider aperture only if not inverted (there is only an output port) + if !self.inverted() { + if let Some(aperture) = self.ports().aperture(&PortType::Output, "out1") { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort( + "output aperture not found".into(), + )); + }; + } } } Ok(LightResult::from([("out1".into(), data)])) diff --git a/opossum/src/nodes/spectrometer.rs b/opossum/src/nodes/spectrometer.rs index 91c8608b0f6e3ca24c219bb7f191df7018201b9a..2b4b53786a9fa83a3b1d9f8ce64c4ff970fda817 100644 --- a/opossum/src/nodes/spectrometer.rs +++ b/opossum/src/nodes/spectrometer.rs @@ -281,28 +281,28 @@ impl AnalysisRayTrace for Spectrometer { if let Some(iso) = self.effective_iso() { self.surface.set_isometry(&iso); rays.refract_on_surface(&mut self.surface, None)?; + if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { + let rays_apodized = rays.apodize(aperture, &iso)?; + if rays_apodized { + warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); + self.apodization_warning = true; + } + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; + self.light_data = Some(LightData::Geometric(rays.clone())); + if let Some(aperture) = self.ports().aperture(&PortType::Output, outport) { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("output aperture not found".into())); + }; } else { return Err(OpossumError::Analysis( "no location for surface defined. Aborting".into(), )); } - if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { - let rays_apodized = rays.apodize(aperture)?; - if rays_apodized { - warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); - self.apodization_warning = true; - } - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; - self.light_data = Some(LightData::Geometric(rays.clone())); - if let Some(aperture) = self.ports().aperture(&PortType::Output, outport) { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("output aperture not found".into())); - }; Ok(LightResult::from([( outport.into(), LightData::Geometric(rays), diff --git a/opossum/src/nodes/spot_diagram.rs b/opossum/src/nodes/spot_diagram.rs index 398cfaece36b55b4fc39d01a87cadc862f2d0bf6..3fcbeedabaca5bca8e2dff436dc75b661940e909 100644 --- a/opossum/src/nodes/spot_diagram.rs +++ b/opossum/src/nodes/spot_diagram.rs @@ -259,34 +259,34 @@ impl AnalysisRayTrace for SpotDiagram { if let Some(iso) = self.effective_iso() { let mut plane = OpticalSurface::new(Box::new(Plane::new(&iso))); rays.refract_on_surface(&mut plane, None)?; + if let Some(aperture) = self.ports().aperture(&PortType::Input, "in1") { + let rays_apodized = rays.apodize(aperture, &iso)?; + if rays_apodized { + warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); + self.apodization_warning = true; + } + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; + if let Some(LightData::Geometric(old_rays)) = &self.light_data { + let mut rays_tob_merged = old_rays.clone(); + rays_tob_merged.merge(&rays); + self.light_data = Some(LightData::Geometric(rays_tob_merged.clone())); + } else { + self.light_data = Some(LightData::Geometric(rays.clone())); + } + if let Some(aperture) = self.ports().aperture(&PortType::Output, "out1") { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("output aperture not found".into())); + }; } else { return Err(OpossumError::Analysis( "no location for surface defined. Aborting".into(), )); } - if let Some(aperture) = self.ports().aperture(&PortType::Input, "in1") { - let rays_apodized = rays.apodize(aperture)?; - if rays_apodized { - warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); - self.apodization_warning = true; - } - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; - if let Some(LightData::Geometric(old_rays)) = &self.light_data { - let mut rays_tob_merged = old_rays.clone(); - rays_tob_merged.merge(&rays); - self.light_data = Some(LightData::Geometric(rays_tob_merged.clone())); - } else { - self.light_data = Some(LightData::Geometric(rays.clone())); - } - if let Some(aperture) = self.ports().aperture(&PortType::Output, "out1") { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("output aperture not found".into())); - }; Ok(LightResult::from([( outport.into(), LightData::Geometric(rays), diff --git a/opossum/src/nodes/thin_mirror.rs b/opossum/src/nodes/thin_mirror.rs index f9f42b650ad5b03a461bb56d65bc47d5b8f39583..d2bd80373967167a21d8a3e8ce7883abb4714b91 100644 --- a/opossum/src/nodes/thin_mirror.rs +++ b/opossum/src/nodes/thin_mirror.rs @@ -181,7 +181,7 @@ impl AnalysisRayTrace for ThinMirror { ); let mut reflected_rays = rays.refract_on_surface(&mut surface, None)?; if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { - reflected_rays.apodize(aperture)?; + reflected_rays.apodize(aperture, &iso)?; reflected_rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; reflected_rays } else { diff --git a/opossum/src/nodes/wavefront.rs b/opossum/src/nodes/wavefront.rs index dc62f47da191b97238b3844fb4cf65b63089f009..adc2f5451d4214a7b0208c7b0531f5e53f64bf07 100644 --- a/opossum/src/nodes/wavefront.rs +++ b/opossum/src/nodes/wavefront.rs @@ -320,28 +320,28 @@ impl AnalysisRayTrace for WaveFront { if let Some(iso) = self.effective_iso() { self.surface.set_isometry(&iso); rays.refract_on_surface(&mut self.surface, None)?; + if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { + let rays_apodized = rays.apodize(aperture, &iso)?; + if rays_apodized { + warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); + self.apodization_warning = true; + } + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("input aperture not found".into())); + }; + self.light_data = Some(LightData::Geometric(rays.clone())); + if let Some(aperture) = self.ports().aperture(&PortType::Output, outport) { + rays.apodize(aperture, &iso)?; + rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; + } else { + return Err(OpossumError::OpticPort("output aperture not found".into())); + }; } else { return Err(OpossumError::Analysis( "no location for surface defined. Aborting".into(), )); } - if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) { - let rays_apodized = rays.apodize(aperture)?; - if rays_apodized { - warn!("Rays have been apodized at input aperture of {}. Results might not be accurate.", self as &mut dyn OpticNode); - self.apodization_warning = true; - } - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; - self.light_data = Some(LightData::Geometric(rays.clone())); - if let Some(aperture) = self.ports().aperture(&PortType::Output, outport) { - rays.apodize(aperture)?; - rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?; - } else { - return Err(OpossumError::OpticPort("output aperture not found".into())); - }; Ok(LightResult::from([( outport.into(), LightData::Geometric(rays), diff --git a/opossum/src/rays.rs b/opossum/src/rays.rs index a32e998cb18cbc41a98010b5c773bf4734e7dd1f..33f2c4d8aeef7753a8b2b2f034692c48d4e04d78 100644 --- a/opossum/src/rays.rs +++ b/opossum/src/rays.rs @@ -355,11 +355,12 @@ impl Rays { /// # Errors /// /// This function returns an error if a single ray cannot be properly apodized (e.g. filter factor outside (0.0..=1.0)). - pub fn apodize(&mut self, aperture: &Aperture) -> OpmResult<bool> { + pub fn apodize(&mut self, aperture: &Aperture, iso: &Isometry) -> OpmResult<bool> { let mut beams_invalided = false; for ray in &mut self.rays { if ray.valid() { - let ap_factor = aperture.apodization_factor(&ray.position().xy()); + let ap_factor = + aperture.apodization_factor(&ray.inverse_transformed_ray(iso).position().xy()); if ap_factor > 0.0 { ray.filter_energy(&FilterType::Constant(ap_factor))?; } else { @@ -1908,7 +1909,7 @@ mod test { assert_eq!(rays.total_energy(), joule!(2.0)); let circle_config = CircleConfig::new(millimeter!(0.5), millimeter!(0.0, 0.0)).unwrap(); let aperture = Aperture::BinaryCircle(circle_config); - rays.apodize(&aperture).unwrap(); + rays.apodize(&aperture, &Isometry::identity()).unwrap(); assert_eq!(rays.total_energy(), joule!(1.0)); } #[test]