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 8380711d3208a257399f2d67796e1d5d616c790e..9d2a8711ee50eecfdfd364fe1e204906e6a97479 100644 --- a/opossum/src/analyzers/raytrace.rs +++ b/opossum/src/analyzers/raytrace.rs @@ -93,10 +93,15 @@ pub trait AnalysisRayTrace: OpticNode { 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())?; } @@ -119,7 +124,7 @@ pub trait AnalysisRayTrace: OpticNode { } 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())?; } @@ -153,6 +158,11 @@ pub trait AnalysisRayTrace: OpticNode { 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 { @@ -170,7 +180,7 @@ pub trait AnalysisRayTrace: OpticNode { } 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())?; } @@ -192,7 +202,7 @@ pub trait AnalysisRayTrace: OpticNode { } 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 cc331698e3b0f5745b098ed60766cbc024a00cfb..a77bb672cf5ecc3133fbb9436093d1db2ab80dcc 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 fdedd1599062cfe8f6a1d79729e920c7e13b81fb..ba0b86de9381ebad6d2a43b2edd762b66be8f9ea 100644 --- a/opossum/src/nodes/detector.rs +++ b/opossum/src/nodes/detector.rs @@ -137,27 +137,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 47e97128cd4fc8a57da991e394c21377dfd90ed8..ef53480d23e479a0314f1ab78ea9fa0af0cda7e3 100644 --- a/opossum/src/nodes/dummy.rs +++ b/opossum/src/nodes/dummy.rs @@ -9,7 +9,9 @@ use crate::{ error::{OpmResult, OpossumError}, light_result::LightResult, lightdata::LightData, - optic_node::{OpticNode, LIDT}, + optic_node::{ + LIDT, {Alignable, OpticNode}, + }, optic_ports::{OpticPorts, PortType}, surface::{OpticalSurface, Plane}, utils::geom_transformation::Isometry, @@ -101,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), @@ -143,6 +146,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 43235726ae27cbec1e4a6605bc029d026e9d2a0c..65e163f0393ed80e1a2922d4e6c5d3e596db2718 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 c4f9a412b154f1e950fc8378438bc3b64308c416..b6f06d95965e08b63dacad2c7c5c4d55fbf35ee4 100644 --- a/opossum/src/nodes/fluence_detector.rs +++ b/opossum/src/nodes/fluence_detector.rs @@ -212,28 +212,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 f6569b4111d951be88027555910579d67b77b2bd..24c29fd15114fc66482379aa92251658b0ca0d71 100644 --- a/opossum/src/nodes/ideal_filter.rs +++ b/opossum/src/nodes/ideal_filter.rs @@ -241,24 +241,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 27468084d5fd95dbb8f73ebc04fc90bddab165a8..fd02634f83a970a0ee6ce0a4e79e2b268e9cdb48 100644 --- a/opossum/src/nodes/paraxial_surface.rs +++ b/opossum/src/nodes/paraxial_surface.rs @@ -139,43 +139,42 @@ impl AnalysisRayTrace for ParaxialSurface { let Some(data) = incoming_data.get(in_port) else { return Ok(LightResult::default()); }; - let LightData::Geometric(mut rays) = data.clone() else { - return Err(OpossumError::Analysis( - "expected ray data at input port".into(), - )); - }; - - let Proptype::Length(focal_length) = self.node_attr.get_property("focal length")?.clone() - else { - return Err(OpossumError::Analysis("cannot read focal length".into())); - }; - let Some(eff_iso) = self.effective_iso() 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())?; + if let LightData::Geometric(mut rays) = data.clone() { + let Ok(Proptype::Length(focal_length)) = self.node_attr.get_property("focal length") + else { + return Err(OpossumError::Analysis("cannot read focal length".into())); + }; + if let Some(iso) = self.effective_iso() { + rays.refract_on_surface( + &mut OpticalSurface::new(Box::new(Plane::new(&iso))), + 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(), + )); + } + let mut light_result = LightResult::default(); + light_result.insert(out_port.into(), LightData::Geometric(rays)); + Ok(light_result) } else { - return Err(OpossumError::OpticPort("input aperture not found".into())); - }; - let surf = self.get_surface_mut(""); - surf.set_isometry(&eff_iso); - - rays.refract_on_surface(surf, None)?; - rays.refract_paraxial(focal_length, &eff_iso)?; - - 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) + Err(crate::error::OpossumError::Analysis( + "No LightData::Geometric for analyzer type RayTrace".into(), + )) + } } } diff --git a/opossum/src/nodes/ray_propagation_visualizer.rs b/opossum/src/nodes/ray_propagation_visualizer.rs index 1f9c59f0c5e34a7902beb0bfd87ff84a42d4f9a4..779f8943c74acef82952aec613094b27db4ffd64 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 73e1f1c5a7c9ac6d9a4a91262f260a30785ff0bf..8d5d1064e3e0110448fa1b7c8038a41f27508fc2 100644 --- a/opossum/src/nodes/reflective_grating.rs +++ b/opossum/src/nodes/reflective_grating.rs @@ -223,7 +223,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 91f4a73d9c08af5ce1a65a7ac2676da46a6773a7..e7a11e527b583932df921076030b59b3ab85eace 100644 --- a/opossum/src/nodes/source.rs +++ b/opossum/src/nodes/source.rs @@ -214,15 +214,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 6e514b464866150773c40255f7168f5121d0bc57..08071af3b2f3cbfa445477751e1f05716ee9e0bc 100644 --- a/opossum/src/nodes/spectrometer.rs +++ b/opossum/src/nodes/spectrometer.rs @@ -280,28 +280,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 29a216c59a701a551e213fd9f2c8bc166b49066a..ca9b4e673edfd48efb57deb2d5ded9b8b6d3a8d0 100644 --- a/opossum/src/nodes/spot_diagram.rs +++ b/opossum/src/nodes/spot_diagram.rs @@ -257,34 +257,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 e313c23e4cf1dbe853b078710557cb8a96aa7d18..d89897d8ff4e61a69372dbce38e069b3a51634bb 100644 --- a/opossum/src/nodes/thin_mirror.rs +++ b/opossum/src/nodes/thin_mirror.rs @@ -191,7 +191,7 @@ impl AnalysisRayTrace for ThinMirror { surface.set_coating(coating); let mut reflected_rays = rays.refract_on_surface(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 3ac9f27bd4349d8b5e3ad26dede2b6701b1a2a45..b0c2d53a101c16b05f0b998261197043aea2757d 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 07a3a1ce0358efb195dff2e4c58297dba52923cd..7a23a091915f5c49729f3e133d2864941572d28f 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]