From 5d5c4d25296c6c22c14aa4ec2a2292ff62dd3e1f Mon Sep 17 00:00:00 2001 From: Udo Eisenbarth <u.eisenbarth@gsi.de> Date: Fri, 25 Oct 2024 14:30:00 +0200 Subject: [PATCH] fix: :bug: Fix error during apodization of rays: Aperture did not consider isometries. --- opossum/examples/apodization.rs | 39 ++++++++++++++++ opossum/examples/rays.rs | 12 ----- opossum/src/analyzers/raytrace.rs | 18 ++++++-- opossum/src/nodes/beam_splitter/mod.rs | 39 +++++++++------- opossum/src/nodes/detector.rs | 32 ++++++------- opossum/src/nodes/dummy.rs | 28 +++++------ opossum/src/nodes/energy_meter.rs | 34 +++++++------- opossum/src/nodes/fluence_detector.rs | 34 +++++++------- opossum/src/nodes/ideal_filter.rs | 26 +++++------ opossum/src/nodes/paraxial_surface.rs | 24 +++++----- .../src/nodes/ray_propagation_visualizer.rs | 40 ++++++++-------- opossum/src/nodes/reflective_grating.rs | 2 +- opossum/src/nodes/source.rs | 20 ++++---- opossum/src/nodes/spectrometer.rs | 34 +++++++------- opossum/src/nodes/spot_diagram.rs | 46 +++++++++---------- opossum/src/nodes/thin_mirror.rs | 2 +- opossum/src/nodes/wavefront.rs | 34 +++++++------- opossum/src/rays.rs | 7 +-- 18 files changed, 260 insertions(+), 211 deletions(-) create mode 100644 opossum/examples/apodization.rs delete mode 100644 opossum/examples/rays.rs diff --git a/opossum/examples/apodization.rs b/opossum/examples/apodization.rs new file mode 100644 index 00000000..707be419 --- /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 cc1a1544..00000000 --- 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 9935e508..e5eca4b1 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 736be84b..6a34d193 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 5a3a2123..c45b833c 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 1ad3ee5c..e5a4cf8c 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 13df2d6d..54dafa48 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 40487103..ff09075b 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 e4a598f8..e766db11 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 4b3287d4..987f461f 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 cef8299d..f7ef9cca 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 4579db76..4cd18960 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 af85f8da..d35ccf5a 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 91c8608b..2b4b5378 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 398cfaec..3fcbeeda 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 f9f42b65..d2bd8037 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 dc62f47d..adc2f545 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 a32e998c..33f2c4d8 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] -- GitLab