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]