diff --git a/opossum/examples/ghost_focus.rs b/opossum/examples/ghost_focus.rs
index 8d7ce67bcf81f499e471146bf4986cc1b1278681..13c76e1313a9c6e213bd7c524c10f02af67e5e61 100644
--- a/opossum/examples/ghost_focus.rs
+++ b/opossum/examples/ghost_focus.rs
@@ -4,11 +4,14 @@ use opossum::{
     degree,
     error::OpmResult,
     joule, millimeter,
-    nodes::{round_collimated_ray_source, Lens, NodeGroup, SpotDiagram, Wedge},
-    optic_node::{Alignable, OpticNode},
+    nodes::{
+        collimated_line_ray_source, round_collimated_ray_source, Lens, NodeGroup, SpotDiagram,
+        Wedge,
+    },
+    optic_node::{Alignable, OpticNode, LIDT},
     optic_ports::PortType,
     refractive_index::RefrIndexConst,
-    OpmDocument,
+    J_per_cm2, OpmDocument,
 };
 use std::path::Path;
 
@@ -16,7 +19,8 @@ fn main() -> OpmResult<()> {
     let mut scenery = NodeGroup::default();
     let i_src = scenery.add_node(
         // collimated_line_ray_source(millimeter!(50.), joule!(1.), 100)?
-        &round_collimated_ray_source(millimeter!(50.0), joule!(1.0), 7)?,
+        &round_collimated_ray_source(millimeter!(50.0), joule!(50.0), 15)?
+            .with_lidt(J_per_cm2!(20.)),
     )?;
     let i_sd = scenery.add_node(&SpotDiagram::default())?;
 
@@ -25,26 +29,31 @@ fn main() -> OpmResult<()> {
     lens.set_coating(&PortType::Output, "rear", &CoatingType::Fresnel)?;
     let i_l = scenery.add_node(&lens)?;
 
+    let mut lens2 = Lens::default();
+    lens2.set_coating(&PortType::Input, "front", &CoatingType::Fresnel)?;
+    lens2.set_coating(&PortType::Output, "rear", &CoatingType::Fresnel)?;
+    let i_l2 = scenery.add_node(&lens2)?;
+
     let mut wedge = Wedge::new(
         "wedge",
         millimeter!(20.0),
-        degree!(10.0),
+        degree!(0.5),
         &RefrIndexConst::new(1.5)?,
     )?
-    .with_tilt(degree!(5.0, 0.0, 0.0))?;
+    .with_tilt(degree!(0.5, 0.0, 0.0))?;
     wedge.set_coating(&PortType::Input, "front", &CoatingType::Fresnel)?;
     wedge.set_coating(&PortType::Output, "rear", &CoatingType::Fresnel)?;
     let i_w = scenery.add_node(&wedge)?;
 
     let i_sd2 = scenery.add_node(&SpotDiagram::default())?;
-    scenery.connect_nodes(i_src, "out1", i_sd, "in1", millimeter!(20.0))?;
-    scenery.connect_nodes(i_sd, "out1", i_l, "front", millimeter!(80.0))?;
-    scenery.connect_nodes(i_l, "rear", i_w, "front", millimeter!(70.0))?;
-    scenery.connect_nodes(i_w, "rear", i_sd2, "in1", millimeter!(70.0))?;
+    scenery.connect_nodes(i_src, "out1", i_l, "front", millimeter!(100.0))?;
+    scenery.connect_nodes(i_l, "rear", i_l2, "front", millimeter!(1000.0))?;
+    // scenery.connect_nodes(i_l2, "rear", i_w, "front", millimeter!(100.0))?;
+    // scenery.connect_nodes(i_w, "rear", i_sd, "in1", millimeter!(50.0))?;
 
     let mut doc = OpmDocument::new(scenery);
     let mut config = GhostFocusConfig::default();
-    config.set_max_bounces(1);
+    config.set_max_bounces(2);
     doc.add_analyzer(AnalyzerType::GhostFocus(config));
     // doc.add_analyzer(AnalyzerType::RayTrace(RayTraceConfig::default()));
     doc.save_to_file(Path::new("./opossum/playground/ghost_focus.opm"))
diff --git a/opossum/files_for_testing/opm/optic_ref.opm b/opossum/files_for_testing/opm/optic_ref.opm
index 0c78e26357c055b84e5fc886bad6b504ebfb159d..514ecd6dee242fb04e556538db910ee375df10d2 100644
--- a/opossum/files_for_testing/opm/optic_ref.opm
+++ b/opossum/files_for_testing/opm/optic_ref.opm
@@ -5,6 +5,7 @@ attributes:
   isometry: null
   name: test123
   uuid: 587ee70f-6f52-4420-89f6-e1618ff4dbdb
+  lidt: 10000.
   ports:
     inputs:
       front: 
diff --git a/opossum/files_for_testing/opm/opticscenery.opm b/opossum/files_for_testing/opm/opticscenery.opm
index 9bafe8e8fe51a3a0002dfc199cd6689d45340302..dcc8a3b5020e6e0b9b7d46134216b2c34a3b0b94 100644
--- a/opossum/files_for_testing/opm/opticscenery.opm
+++ b/opossum/files_for_testing/opm/opticscenery.opm
@@ -6,6 +6,7 @@ scenery:
       inputs: {}
       outputs: {}
     uuid: b8cb049b-4eb9-4db8-8842-2fc7c70c27ba
+    lidt: 10000.
     props:
       expand view: !Bool false
       graph: !OpticGraph
@@ -15,6 +16,7 @@ scenery:
           attributes:
             name: dummy1
             uuid: 180328fe-7ad4-4568-b501-183b88c4daee
+            lidt: 10000.
             ports:
               inputs:
                 front:
@@ -31,6 +33,7 @@ scenery:
           attributes:
             name: dummy2
             uuid: 642ce76e-b071-43c0-a77e-1bdbb99b40d8
+            lidt: 10000.
             ports:
               inputs:
                 front:
diff --git a/opossum/src/analyzers/analyzable.rs b/opossum/src/analyzers/analyzable.rs
index b87f97471f21a04bb267652b661b642ba738ad61..0e3b596f6f1066dce3766ac6f83ad392d11732af 100644
--- a/opossum/src/analyzers/analyzable.rs
+++ b/opossum/src/analyzers/analyzable.rs
@@ -7,16 +7,13 @@ use crate::{
     error::{OpmResult, OpossumError},
     optic_node::OpticNode,
     optic_ports::PortType,
-    surface::Surface,
     utils::geom_transformation::Isometry,
 };
 use core::fmt::Debug;
 use std::fmt::Display;
 
 /// Marker trait for an optical node that can be analyzed
-pub trait Analyzable:
-    OpticNode + AnalysisEnergy + AnalysisRayTrace + AnalysisGhostFocus + Surface
-{
+pub trait Analyzable: OpticNode + AnalysisEnergy + AnalysisRayTrace + AnalysisGhostFocus {
     ///Sets the coating and isometry of this surface
     /// # Errors
     /// This function errors if the coating cannot be accessed
diff --git a/opossum/src/analyzers/ghostfocus.rs b/opossum/src/analyzers/ghostfocus.rs
index 8b5d76d89e4d9137f496eee75aee4f73fb02c145..59485bdc31264b07055f0b9f4adb9d657b9dc3b0 100644
--- a/opossum/src/analyzers/ghostfocus.rs
+++ b/opossum/src/analyzers/ghostfocus.rs
@@ -380,13 +380,13 @@ impl GhostFocusHistory {
     pub fn rays_origin_report_str(&self, graph: &OpticGraph) -> String {
         let mut report_str = String::new();
         for (bounce, rays_correlation) in self.ray_node_correlation.iter().enumerate() {
-            if bounce == 0 {
-                report_str += "Origin at node '";
-            } else {
-                report_str += format!("bounce {bounce} at node '").as_str();
-            }
             for rays_origin in rays_correlation.values() {
                 if let Some(node_uuid) = rays_origin.node_origin {
+                    if bounce == 0 {
+                        report_str += "Origin at node '";
+                    } else {
+                        report_str += format!("bounce {bounce} at node '").as_str();
+                    }
                     if let Some(opt_ref) = graph.node_by_uuid(node_uuid) {
                         report_str +=
                             format!("{}', ", opt_ref.optical_ref.borrow().name()).as_str();
@@ -511,11 +511,11 @@ impl Plottable for GhostFocusHistory {
                 let plt_data = PlotData::MultiDim2 {
                     vec_of_xy_data: proj_pos_mm,
                 };
-
                 let series_label = format!("Bounce: {i}");
+
                 plt_series.push(PlotSeries::new(
                     &plt_data,
-                    RGBAColor(c.r, c.g, c.b, 1.),
+                    RGBAColor(c.r, c.g, c.b, 0.1),
                     Some(series_label),
                 ));
             }
diff --git a/opossum/src/analyzers/raytrace.rs b/opossum/src/analyzers/raytrace.rs
index e5eca4b199d50900e6e51f94f01c368e9355832d..9d2a8711ee50eecfdfd364fe1e204906e6a97479 100644
--- a/opossum/src/analyzers/raytrace.rs
+++ b/opossum/src/analyzers/raytrace.rs
@@ -13,7 +13,6 @@ use crate::{
     rays::Rays,
     refractive_index::RefractiveIndexType,
     reporting::analysis_report::AnalysisReport,
-    surface::Surface,
     utils::geom_transformation::Isometry,
 };
 use log::info;
@@ -55,7 +54,7 @@ impl Analyzer for RayTracingAnalyzer {
     }
 }
 /// Trait for implementing the ray trace analysis.
-pub trait AnalysisRayTrace: OpticNode + Surface {
+pub trait AnalysisRayTrace: OpticNode {
     /// Perform a ray trace analysis an [`OpticNode`].
     ///
     /// # Errors
diff --git a/opossum/src/nodes/beam_splitter/mod.rs b/opossum/src/nodes/beam_splitter/mod.rs
index 6a34d1932f6124d790ad84fb6beb12c94cff2f3e..a77bb672cf5ecc3133fbb9436093d1db2ab80dcc 100644
--- a/opossum/src/nodes/beam_splitter/mod.rs
+++ b/opossum/src/nodes/beam_splitter/mod.rs
@@ -15,7 +15,7 @@ use crate::{
     ray::SplittingConfig,
     rays::Rays,
     spectrum::{merge_spectra, Spectrum},
-    surface::{OpticalSurface, Plane, Surface},
+    surface::{OpticalSurface, Plane},
     utils::EnumProxy,
 };
 
@@ -301,6 +301,10 @@ impl OpticNode for BeamSplitter {
     fn node_attr_mut(&mut self) -> &mut NodeAttr {
         &mut self.node_attr
     }
+
+    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
+        todo!()
+    }
 }
 
 impl Dottable for BeamSplitter {
@@ -308,11 +312,7 @@ impl Dottable for BeamSplitter {
         "lightpink"
     }
 }
-impl Surface for BeamSplitter {
-    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
-    }
-}
+
 impl Analyzable for BeamSplitter {}
 impl AnalysisGhostFocus for BeamSplitter {}
 
diff --git a/opossum/src/nodes/cylindric_lens/analysis_ghostfocus.rs b/opossum/src/nodes/cylindric_lens/analysis_ghostfocus.rs
index 2749990c60f5f074fb1a3a3644142e704fd32dce..832b13506b380aea0584343777877547fb178639 100644
--- a/opossum/src/nodes/cylindric_lens/analysis_ghostfocus.rs
+++ b/opossum/src/nodes/cylindric_lens/analysis_ghostfocus.rs
@@ -43,10 +43,9 @@ impl AnalysisGhostFocus for CylindricLens {
             )?;
         };
 
-        let Some(incoming_rays) = incoming_data.get(in_port) else {
-            return Ok(LightRays::default());
-        };
-        let mut rays_bundle = incoming_rays.clone();
+        let mut rays_bundle = incoming_data
+            .get(in_port)
+            .map_or_else(Vec::<Rays>::new, std::clone::Clone::clone);
 
         self.enter_through_surface(
             &mut rays_bundle,
diff --git a/opossum/src/nodes/cylindric_lens/mod.rs b/opossum/src/nodes/cylindric_lens/mod.rs
index 1d96efa4eb55f7c173e1663ce4ab03ec84e22c5e..4df97a51c2e6deb029b41a0ec8ee722bc501241c 100644
--- a/opossum/src/nodes/cylindric_lens/mod.rs
+++ b/opossum/src/nodes/cylindric_lens/mod.rs
@@ -8,12 +8,12 @@ use crate::{
     dottable::Dottable,
     error::{OpmResult, OpossumError},
     millimeter,
-    optic_node::{Alignable, OpticNode},
+    optic_node::{Alignable, OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     properties::Proptype,
     rays::Rays,
     refractive_index::{RefrIndexConst, RefractiveIndex, RefractiveIndexType},
-    surface::{hit_map::HitMap, Cylinder, OpticalSurface, Plane, Surface},
+    surface::{hit_map::HitMap, Cylinder, OpticalSurface, Plane},
     utils::{geom_transformation::Isometry, EnumProxy},
 };
 #[cfg(feature = "bevy")]
@@ -157,6 +157,9 @@ impl CylindricLens {
         lens.update_surfaces()?;
         Ok(lens)
     }
+}
+
+impl OpticNode for CylindricLens {
     fn update_surfaces(&mut self) -> OpmResult<()> {
         let Ok(Proptype::Length(front_roc)) = self.node_attr.get_property("front curvature") else {
             return Err(OpossumError::Analysis("cannot read front curvature".into()));
@@ -176,9 +179,6 @@ impl CylindricLens {
         };
         Ok(())
     }
-}
-
-impl OpticNode for CylindricLens {
     fn reset_data(&mut self) {
         self.front_surf.set_backwards_rays_cache(Vec::<Rays>::new());
         self.front_surf.set_forward_rays_cache(Vec::<Rays>::new());
@@ -201,8 +201,12 @@ impl OpticNode for CylindricLens {
     fn node_attr_mut(&mut self) -> &mut NodeAttr {
         &mut self.node_attr
     }
-    fn after_deserialization_hook(&mut self) -> OpmResult<()> {
-        self.update_surfaces()
+    fn get_surface_mut(&mut self, surf_name: &str) -> &mut OpticalSurface {
+        if surf_name == "front" {
+            &mut self.front_surf
+        } else {
+            &mut self.rear_surf
+        }
     }
 }
 
@@ -213,15 +217,8 @@ impl Dottable for CylindricLens {
         "aqua"
     }
 }
-impl Surface for CylindricLens {
-    fn get_surface_mut(&mut self, surf_name: &str) -> &mut OpticalSurface {
-        if surf_name == "front" {
-            &mut self.front_surf
-        } else {
-            &mut self.rear_surf
-        }
-    }
-}
+
+impl LIDT for CylindricLens {}
 impl Analyzable for CylindricLens {}
 
 #[cfg(test)]
diff --git a/opossum/src/nodes/detector.rs b/opossum/src/nodes/detector.rs
index c45b833c06a8d61580a38783b779e695f1566264..ba0b86de9381ebad6d2a43b2edd762b66be8f9ea 100644
--- a/opossum/src/nodes/detector.rs
+++ b/opossum/src/nodes/detector.rs
@@ -9,9 +9,9 @@ use crate::{
     error::{OpmResult, OpossumError},
     light_result::LightResult,
     lightdata::LightData,
-    optic_node::OpticNode,
+    optic_node::{OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
-    surface::{OpticalSurface, Plane, Surface},
+    surface::{OpticalSurface, Plane},
     utils::geom_transformation::Isometry,
 };
 use log::warn;
@@ -82,6 +82,9 @@ impl OpticNode for Detector {
         self.light_data = None;
         self.surface.reset_hit_map();
     }
+    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
+        &mut self.surface
+    }
 }
 
 impl Debug for Detector {
@@ -97,6 +100,8 @@ impl Dottable for Detector {
         "lemonchiffon"
     }
 }
+impl LIDT for Detector {}
+
 impl Analyzable for Detector {}
 impl AnalysisGhostFocus for Detector {}
 impl AnalysisEnergy for Detector {
@@ -170,11 +175,6 @@ impl AnalysisRayTrace for Detector {
     }
 }
 
-impl Surface for Detector {
-    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
-    }
-}
 #[cfg(test)]
 mod test {
     use super::*;
diff --git a/opossum/src/nodes/dummy.rs b/opossum/src/nodes/dummy.rs
index e5a4cf8cb2bcb8ec01a48679f807fbabaa804ce8..f863b4e5351f831c8c816e8db557eeadda15a44c 100644
--- a/opossum/src/nodes/dummy.rs
+++ b/opossum/src/nodes/dummy.rs
@@ -9,9 +9,9 @@ use crate::{
     error::{OpmResult, OpossumError},
     light_result::LightResult,
     lightdata::LightData,
-    optic_node::{Alignable, OpticNode},
+    optic_node::{{Alignable, OpticNode}, LIDT},
     optic_ports::{OpticPorts, PortType},
-    surface::{OpticalSurface, Plane, Surface},
+    surface::{OpticalSurface, Plane},
     utils::geom_transformation::Isometry,
 };
 
@@ -64,6 +64,8 @@ impl Dummy {
         dummy
     }
 }
+impl LIDT for Dummy {}
+
 impl Analyzable for Dummy {}
 impl AnalysisGhostFocus for Dummy {}
 impl AnalysisEnergy for Dummy {
@@ -79,11 +81,7 @@ impl AnalysisEnergy for Dummy {
         )
     }
 }
-impl Surface for Dummy {
-    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
-    }
-}
+
 impl AnalysisRayTrace for Dummy {
     fn analyze(
         &mut self,
@@ -141,6 +139,9 @@ impl OpticNode for Dummy {
     fn reset_data(&mut self) {
         self.surface.reset_hit_map();
     }
+    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
+        &mut self.surface
+    }
 }
 
 impl Alignable for Dummy {}
diff --git a/opossum/src/nodes/energy_meter.rs b/opossum/src/nodes/energy_meter.rs
index 54dafa482c63dd6ad3e24cc9f3478609656fc92d..65e163f0393ed80e1a2922d4e6c5d3e596db2718 100644
--- a/opossum/src/nodes/energy_meter.rs
+++ b/opossum/src/nodes/energy_meter.rs
@@ -9,11 +9,11 @@ use crate::{
     joule,
     light_result::LightResult,
     lightdata::LightData,
-    optic_node::OpticNode,
+    optic_node::{OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     properties::{Properties, Proptype},
     reporting::node_report::NodeReport,
-    surface::{OpticalSurface, Plane, Surface},
+    surface::{OpticalSurface, Plane},
     utils::geom_transformation::Isometry,
 };
 use log::warn;
@@ -196,12 +196,11 @@ impl OpticNode for EnergyMeter {
         self.light_data = None;
         self.surface.reset_hit_map();
     }
-}
-impl Surface for EnergyMeter {
     fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
+        &mut self.surface
     }
 }
+
 impl Debug for EnergyMeter {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match &self.light_data {
@@ -215,6 +214,7 @@ impl Dottable for EnergyMeter {
         "whitesmoke"
     }
 }
+impl LIDT for EnergyMeter {}
 impl Analyzable for EnergyMeter {}
 impl AnalysisGhostFocus for EnergyMeter {}
 impl AnalysisEnergy for EnergyMeter {
diff --git a/opossum/src/nodes/fluence_detector.rs b/opossum/src/nodes/fluence_detector.rs
index ff09075b6ec95075f96bc01fb9dab4375ac16648..b6f06d95965e08b63dacad2c7c5c4d55fbf35ee4 100644
--- a/opossum/src/nodes/fluence_detector.rs
+++ b/opossum/src/nodes/fluence_detector.rs
@@ -16,13 +16,13 @@ use crate::{
     error::{OpmResult, OpossumError},
     light_result::{LightRays, LightResult},
     lightdata::LightData,
-    optic_node::OpticNode,
+    optic_node::{OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     plottable::{PlotArgs, PlotData, PlotParameters, PlotSeries, PlotType, Plottable},
     properties::{Properties, Proptype},
     rays::Rays,
     reporting::node_report::NodeReport,
-    surface::{OpticalSurface, Plane, Surface},
+    surface::{OpticalSurface, Plane},
     utils::geom_transformation::Isometry,
 };
 
@@ -78,36 +78,11 @@ impl FluenceDetector {
         fld
     }
 }
-impl Surface for FluenceDetector {
+
+impl OpticNode for FluenceDetector {
     fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
+        &mut self.surface
     }
-}
-impl OpticNode for FluenceDetector {
-    // fn export_data(&self, report_dir: &Path, uuid: &str) -> OpmResult<()> {
-    //     self.light_data.as_ref().map_or_else(
-    //         || {
-    //             Err(OpossumError::Other(
-    //                 "Fluence detector: no light data for export available".into(),
-    //             ))
-    //         },
-    //         |rays| {
-    //             let file_path = PathBuf::from(report_dir).join(Path::new(&format!(
-    //                 "fluence_{}_{}.png",
-    //                 self.name(),
-    //                 uuid
-    //             )));
-    //             let _ = rays.calc_fluence_at_position().map_or_else(
-    //                 |_| {
-    //                     warn!("Fluence Detector diagram: no fluence data for export available",);
-    //                     Ok(None)
-    //                 },
-    //                 |fluence_data| fluence_data.to_plot(&file_path, PltBackEnd::Bitmap),
-    //             );
-    //             Ok(())
-    //         },
-    //     )
-    // }
     fn node_report(&self, uuid: &str) -> Option<NodeReport> {
         let mut props = Properties::default();
         let data = &self.light_data;
@@ -152,12 +127,6 @@ impl OpticNode for FluenceDetector {
                 }
             }
         }
-        // else if let Some(LightData::GhostFocus(v_rays)) = data{
-        //     todo!()
-        // }
-        // else{
-        //     todo!()
-        // }
         Some(NodeReport::new(
             &self.node_type(),
             &self.name(),
@@ -182,6 +151,7 @@ impl Dottable for FluenceDetector {
         "hotpink"
     }
 }
+impl LIDT for FluenceDetector {}
 impl Analyzable for FluenceDetector {}
 impl AnalysisGhostFocus for FluenceDetector {
     fn analyze(
diff --git a/opossum/src/nodes/ideal_filter.rs b/opossum/src/nodes/ideal_filter.rs
index e766db11367f63174aad42524346c81e4936bfef..24c29fd15114fc66482379aa92251658b0ca0d71 100644
--- a/opossum/src/nodes/ideal_filter.rs
+++ b/opossum/src/nodes/ideal_filter.rs
@@ -9,11 +9,11 @@ use crate::{
     error::{OpmResult, OpossumError},
     light_result::LightResult,
     lightdata::LightData,
-    optic_node::OpticNode,
+    optic_node::{OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     properties::Proptype,
     spectrum::Spectrum,
-    surface::{OpticalSurface, Plane, Surface},
+    surface::{OpticalSurface, Plane},
     utils::{geom_transformation::Isometry, EnumProxy},
 };
 use serde::{Deserialize, Serialize};
@@ -181,6 +181,9 @@ impl OpticNode for IdealFilter {
     fn reset_data(&mut self) {
         self.surface.reset_hit_map();
     }
+    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
+        &mut self.surface
+    }
 }
 
 impl Dottable for IdealFilter {
@@ -188,6 +191,7 @@ impl Dottable for IdealFilter {
         "darkgray"
     }
 }
+impl LIDT for IdealFilter {}
 impl Analyzable for IdealFilter {}
 impl AnalysisGhostFocus for IdealFilter {}
 impl AnalysisEnergy for IdealFilter {
@@ -209,11 +213,6 @@ impl AnalysisEnergy for IdealFilter {
         }
     }
 }
-impl Surface for IdealFilter {
-    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
-    }
-}
 impl AnalysisRayTrace for IdealFilter {
     fn analyze(
         &mut self,
diff --git a/opossum/src/nodes/lens/analysis_ghostfocus.rs b/opossum/src/nodes/lens/analysis_ghostfocus.rs
index 357c4ba8786e432ed285f607b5bd96c27c1d595b..b4afd3f63e2f8637a0e2dc60f9e3f2b2a7e03be6 100644
--- a/opossum/src/nodes/lens/analysis_ghostfocus.rs
+++ b/opossum/src/nodes/lens/analysis_ghostfocus.rs
@@ -24,9 +24,10 @@ impl AnalysisGhostFocus for Lens {
             self.get_node_attributes_ray_trace(&self.node_attr)?;
         let in_port = &self.ports().names(&PortType::Input)[0];
         let out_port = &self.ports().names(&PortType::Output)[0];
-        let Some(incoming_rays) = incoming_data.get(in_port) else {
-            return Ok(LightRays::default());
-        };
+        let mut rays_bundle = incoming_data
+            .get(in_port)
+            .map_or_else(Vec::<Rays>::new, std::clone::Clone::clone);
+
         let thickness_iso: Isometry = Isometry::new_along_z(center_thickness)?;
 
         if self.inverted() {
@@ -45,7 +46,6 @@ impl AnalysisGhostFocus for Lens {
             )?;
         };
 
-        let mut rays_bundle = incoming_rays.clone();
         self.enter_through_surface(
             &mut rays_bundle,
             &AnalyzerType::GhostFocus(config.clone()),
diff --git a/opossum/src/nodes/lens/mod.rs b/opossum/src/nodes/lens/mod.rs
index 053d75ed213b19865969e8505b875ed2d0bc8cf4..d321dd7aafea9a1032e00c419c7c5ffbe8f41cb5 100644
--- a/opossum/src/nodes/lens/mod.rs
+++ b/opossum/src/nodes/lens/mod.rs
@@ -8,12 +8,12 @@ use crate::{
     dottable::Dottable,
     error::{OpmResult, OpossumError},
     millimeter,
-    optic_node::{Alignable, OpticNode},
+    optic_node::{Alignable, OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     properties::Proptype,
     rays::Rays,
     refractive_index::{RefrIndexConst, RefractiveIndex, RefractiveIndexType},
-    surface::{hit_map::HitMap, OpticalSurface, Plane, Sphere, Surface},
+    surface::{hit_map::HitMap, OpticalSurface, Plane, Sphere},
     utils::{geom_transformation::Isometry, EnumProxy},
 };
 #[cfg(feature = "bevy")]
@@ -157,25 +157,7 @@ impl Lens {
         lens.update_surfaces()?;
         Ok(lens)
     }
-    fn update_surfaces(&mut self) -> OpmResult<()> {
-        let Ok(Proptype::Length(front_roc)) = self.node_attr.get_property("front curvature") else {
-            return Err(OpossumError::Analysis("cannot read front curvature".into()));
-        };
-        self.front_surf = if front_roc.is_infinite() {
-            OpticalSurface::new(Box::new(Plane::new(&Isometry::identity())))
-        } else {
-            OpticalSurface::new(Box::new(Sphere::new(*front_roc, &Isometry::identity())?))
-        };
-        let Ok(Proptype::Length(rear_roc)) = self.node_attr.get_property("rear curvature") else {
-            return Err(OpossumError::Analysis("cannot read rear curvature".into()));
-        };
-        self.rear_surf = if rear_roc.is_infinite() {
-            OpticalSurface::new(Box::new(Plane::new(&Isometry::identity())))
-        } else {
-            OpticalSurface::new(Box::new(Sphere::new(*rear_roc, &Isometry::identity())?))
-        };
-        Ok(())
-    }
+
     /// create a default aperture: defined by
     ///  - intersection of two spheres
     ///  - intersection of sphere and plane
@@ -264,17 +246,26 @@ impl Lens {
     }
 }
 
-impl Surface for Lens {
-    fn get_surface_mut(&mut self, surf_name: &str) -> &mut OpticalSurface {
-        if surf_name == "front" {
-            &mut self.front_surf
+impl OpticNode for Lens {
+    fn update_surfaces(&mut self) -> OpmResult<()> {
+        let Ok(Proptype::Length(front_roc)) = self.node_attr.get_property("front curvature") else {
+            return Err(OpossumError::Analysis("cannot read front curvature".into()));
+        };
+        self.front_surf = if front_roc.is_infinite() {
+            OpticalSurface::new(Box::new(Plane::new(&Isometry::identity())))
         } else {
-            &mut self.rear_surf
-        }
+            OpticalSurface::new(Box::new(Sphere::new(*front_roc, &Isometry::identity())?))
+        };
+        let Ok(Proptype::Length(rear_roc)) = self.node_attr.get_property("rear curvature") else {
+            return Err(OpossumError::Analysis("cannot read rear curvature".into()));
+        };
+        self.rear_surf = if rear_roc.is_infinite() {
+            OpticalSurface::new(Box::new(Plane::new(&Isometry::identity())))
+        } else {
+            OpticalSurface::new(Box::new(Sphere::new(*rear_roc, &Isometry::identity())?))
+        };
+        Ok(())
     }
-}
-
-impl OpticNode for Lens {
     fn reset_data(&mut self) {
         self.front_surf.set_backwards_rays_cache(Vec::<Rays>::new());
         self.front_surf.set_forward_rays_cache(Vec::<Rays>::new());
@@ -296,8 +287,12 @@ impl OpticNode for Lens {
     fn node_attr_mut(&mut self) -> &mut NodeAttr {
         &mut self.node_attr
     }
-    fn after_deserialization_hook(&mut self) -> OpmResult<()> {
-        self.update_surfaces()
+    fn get_surface_mut(&mut self, surf_name: &str) -> &mut OpticalSurface {
+        if surf_name == "front" {
+            &mut self.front_surf
+        } else {
+            &mut self.rear_surf
+        }
     }
 }
 // impl SDF for Lens
@@ -310,6 +305,7 @@ impl OpticNode for Lens {
 // }
 impl Alignable for Lens {}
 impl Analyzable for Lens {}
+impl LIDT for Lens {}
 
 impl Dottable for Lens {
     fn node_color(&self) -> &str {
diff --git a/opossum/src/nodes/node_attr.rs b/opossum/src/nodes/node_attr.rs
index 9c6eeef07256e46baa429b5e195ae773a279c74c..05ee89278440fa2eb55faaf284f7d8b5e6058b16 100644
--- a/opossum/src/nodes/node_attr.rs
+++ b/opossum/src/nodes/node_attr.rs
@@ -14,8 +14,11 @@ use crate::{
     optic_senery_rsc::SceneryResources,
     properties::{PropCondition, Properties, Proptype},
     utils::geom_transformation::Isometry,
+    J_per_cm2,
 };
 
+use super::fluence_detector::Fluence;
+
 /// Struct for sotring common attributes of optical nodes.
 #[derive(Debug, Clone, Serialize, Deserialize)]
 pub struct NodeAttr {
@@ -24,6 +27,7 @@ pub struct NodeAttr {
     name: String,
     ports: OpticPorts,
     uuid: Uuid,
+    lidt: Fluence,
     #[serde(default)]
     props: Properties,
     #[serde(skip_serializing_if = "Option::is_none")]
@@ -71,6 +75,7 @@ impl NodeAttr {
             alignment: None,
             align_like_node_at_distance: None,
             uuid: Uuid::new_v4(),
+            lidt: J_per_cm2!(1.),
         }
     }
     /// Returns the name property of this node.
@@ -211,6 +216,16 @@ impl NodeAttr {
         self.uuid = *uuid;
     }
 
+    /// Returns a reference to the lidt of this [`NodeAttr`].
+    #[must_use]
+    pub const fn lidt(&self) -> &Fluence {
+        &self.lidt
+    }
+    ///Sets the lidt of this [`NodeAttr`].
+    pub fn set_lidt(&mut self, lidt: &Fluence) {
+        self.lidt = *lidt;
+    }
+
     /// set the nodeindex and distance of the node to which this node should be aligned to
     pub fn set_align_like_node_at_distance(&mut self, node_idx: NodeIndex, distance: Length) {
         self.align_like_node_at_distance = Some((node_idx, distance));
diff --git a/opossum/src/nodes/node_group/mod.rs b/opossum/src/nodes/node_group/mod.rs
index 2efdc2c1e90668a91f77b0d18d87a69b9500d204..7432ac8bb26ae5d7d11205aadaf3d177987b1f96 100644
--- a/opossum/src/nodes/node_group/mod.rs
+++ b/opossum/src/nodes/node_group/mod.rs
@@ -16,7 +16,7 @@ use crate::{
     properties::{Properties, Proptype},
     rays::Rays,
     reporting::{analysis_report::AnalysisReport, node_report::NodeReport},
-    surface::{OpticalSurface, Surface},
+    surface::OpticalSurface,
     utils::EnumProxy,
     SceneryResources,
 };
@@ -507,9 +507,6 @@ impl OpticNode for NodeGroup {
         }
         self.accumulated_rays = Vec::<HashMap<Uuid, Rays>>::new();
     }
-}
-
-impl Surface for NodeGroup {
     fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
         todo!()
     }
diff --git a/opossum/src/nodes/paraxial_surface.rs b/opossum/src/nodes/paraxial_surface.rs
index 987f461f7f9e1061e27fdd4e0103261ce7e35b37..fd02634f83a970a0ee6ce0a4e79e2b268e9cdb48 100644
--- a/opossum/src/nodes/paraxial_surface.rs
+++ b/opossum/src/nodes/paraxial_surface.rs
@@ -10,10 +10,11 @@ use crate::{
     light_result::LightResult,
     lightdata::LightData,
     millimeter,
-    optic_node::{Alignable, OpticNode},
+    optic_node::{Alignable, OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     properties::Proptype,
-    surface::{OpticalSurface, Plane, Surface},
+    surface::{OpticalSurface, Plane},
+    utils::geom_transformation::Isometry,
 };
 use uom::{num_traits::Zero, si::f64::Length};
 
@@ -42,6 +43,7 @@ use super::node_attr::NodeAttr;
 #[derive(Debug, Clone)]
 pub struct ParaxialSurface {
     node_attr: NodeAttr,
+    surface: OpticalSurface,
 }
 impl Default for ParaxialSurface {
     /// Create a default paraxial surface (ideal thin lens) with a focal length of 10 mm.
@@ -61,7 +63,10 @@ impl Default for ParaxialSurface {
                 millimeter!(10.0).into(),
             )
             .unwrap();
-        Self { node_attr }
+        Self {
+            node_attr,
+            surface: OpticalSurface::new(Box::new(Plane::new(&Isometry::identity()))),
+        }
     }
 }
 impl ParaxialSurface {
@@ -94,6 +99,9 @@ impl OpticNode for ParaxialSurface {
     fn node_attr_mut(&mut self) -> &mut NodeAttr {
         &mut self.node_attr
     }
+    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
+        &mut self.surface
+    }
 }
 
 impl Alignable for ParaxialSurface {}
@@ -103,6 +111,7 @@ impl Dottable for ParaxialSurface {
         "palegreen"
     }
 }
+impl LIDT for ParaxialSurface {}
 impl Analyzable for ParaxialSurface {}
 impl AnalysisGhostFocus for ParaxialSurface {}
 impl AnalysisEnergy for ParaxialSurface {
@@ -118,22 +127,15 @@ impl AnalysisEnergy for ParaxialSurface {
         Ok(LightResult::from([(outport.into(), data.clone())]))
     }
 }
-impl Surface for ParaxialSurface {
-    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
-    }
-}
 impl AnalysisRayTrace for ParaxialSurface {
     fn analyze(
         &mut self,
         incoming_data: LightResult,
         config: &RayTraceConfig,
     ) -> OpmResult<LightResult> {
-        let (in_port, out_port) = if self.inverted() {
-            ("rear", "front")
-        } else {
-            ("front", "rear")
-        };
+        let in_port = &self.ports().names(&PortType::Input)[0];
+        let out_port = &self.ports().names(&PortType::Output)[0];
+
         let Some(data) = incoming_data.get(in_port) else {
             return Ok(LightResult::default());
         };
diff --git a/opossum/src/nodes/ray_propagation_visualizer.rs b/opossum/src/nodes/ray_propagation_visualizer.rs
index f7ef9ccabd5d4b6f2a709deb3de0653e62ccccd1..779f8943c74acef82952aec613094b27db4ffd64 100644
--- a/opossum/src/nodes/ray_propagation_visualizer.rs
+++ b/opossum/src/nodes/ray_propagation_visualizer.rs
@@ -20,13 +20,13 @@ use crate::{
     light_result::{LightRays, LightResult},
     lightdata::LightData,
     millimeter,
-    optic_node::OpticNode,
+    optic_node::{OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     plottable::{PlotArgs, PlotData, PlotParameters, PlotSeries, PlotType, Plottable},
     properties::{Properties, Proptype},
     rays::Rays,
     reporting::node_report::NodeReport,
-    surface::{OpticalSurface, Plane, Surface},
+    surface::{OpticalSurface, Plane},
     utils::geom_transformation::Isometry,
 };
 /// A ray-propagation monitor
@@ -92,11 +92,7 @@ impl RayPropagationVisualizer {
         Ok(rpv)
     }
 }
-impl Surface for RayPropagationVisualizer {
-    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
-    }
-}
+
 impl OpticNode for RayPropagationVisualizer {
     fn node_report(&self, uuid: &str) -> Option<NodeReport> {
         let mut props = Properties::default();
@@ -144,6 +140,9 @@ impl OpticNode for RayPropagationVisualizer {
         self.light_data = None;
         self.surface.reset_hit_map();
     }
+    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
+        &mut self.surface
+    }
 }
 
 impl Dottable for RayPropagationVisualizer {
@@ -151,6 +150,7 @@ impl Dottable for RayPropagationVisualizer {
         "darkgreen"
     }
 }
+impl LIDT for RayPropagationVisualizer {}
 impl Analyzable for RayPropagationVisualizer {}
 impl AnalysisGhostFocus for RayPropagationVisualizer {
     fn analyze(
diff --git a/opossum/src/nodes/reference.rs b/opossum/src/nodes/reference.rs
index 5a7b8613139420d0e4f62cadefe4542fd7ca1a30..8165eb595355e319614b1d7c6613114168170cc5 100644
--- a/opossum/src/nodes/reference.rs
+++ b/opossum/src/nodes/reference.rs
@@ -12,10 +12,10 @@ use crate::{
     dottable::Dottable,
     error::{OpmResult, OpossumError},
     light_result::LightResult,
-    optic_node::OpticNode,
+    optic_node::{OpticNode, LIDT},
     optic_ports::OpticPorts,
     optic_ref::OpticRef,
-    surface::{OpticalSurface, Surface},
+    surface::OpticalSurface,
     utils::geom_transformation::Isometry,
 };
 
@@ -119,6 +119,14 @@ impl OpticNode for NodeReference {
         // setting an isometry is silently ignored. Isometry is defined by the refrenced node.
         // self.node_attr.set_isometry(isometry);
     }
+    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
+        todo!()
+        // self.reference.as_ref().and_then(|rf| {
+        //     let ref_node = rf.upgrade().unwrap();
+        //     let node = ref_node.borrow();
+        //     node.get_surface_mut()
+        // })
+    }
 }
 
 impl Dottable for NodeReference {
@@ -126,11 +134,8 @@ impl Dottable for NodeReference {
         "lightsalmon3"
     }
 }
-impl Surface for NodeReference {
-    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
-    }
-}
+
+impl LIDT for NodeReference {}
 impl Analyzable for NodeReference {}
 impl AnalysisGhostFocus for NodeReference {}
 impl AnalysisEnergy for NodeReference {
diff --git a/opossum/src/nodes/reflective_grating.rs b/opossum/src/nodes/reflective_grating.rs
index 4cd18960b416d3c1448bd27db7e2dfd197b8f913..8d5d1064e3e0110448fa1b7c8038a41f27508fc2 100644
--- a/opossum/src/nodes/reflective_grating.rs
+++ b/opossum/src/nodes/reflective_grating.rs
@@ -13,12 +13,13 @@ use crate::{
     light_result::LightResult,
     lightdata::LightData,
     num_per_mm,
-    optic_node::{Alignable, OpticNode},
+    optic_node::{Alignable, OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     properties::Proptype,
     radian,
     refractive_index::refr_index_vaccuum,
-    surface::{OpticalSurface, Plane, Surface},
+    surface::{OpticalSurface, Plane},
+    utils::geom_transformation::Isometry,
 };
 use approx::relative_eq;
 use nalgebra::Vector3;
@@ -48,6 +49,7 @@ pub type LinearDensity = uom::si::f64::LinearNumberDensity;
 ///   - `line density`
 pub struct ReflectiveGrating {
     node_attr: NodeAttr,
+    surface: OpticalSurface,
 }
 impl Default for ReflectiveGrating {
     /// Create a reflective grating with a specified line density.
@@ -73,7 +75,10 @@ impl Default for ReflectiveGrating {
         ports.add(&PortType::Input, "input").unwrap();
         ports.add(&PortType::Output, "diffracted").unwrap();
         node_attr.set_ports(ports);
-        Self { node_attr }
+        Self {
+            node_attr,
+            surface: OpticalSurface::new(Box::new(Plane::new(&Isometry::identity()))),
+        }
     }
 }
 
@@ -161,11 +166,7 @@ impl Dottable for ReflectiveGrating {
         "cornsilk"
     }
 }
-impl Surface for ReflectiveGrating {
-    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
-    }
-}
+impl LIDT for ReflectiveGrating {}
 impl Analyzable for ReflectiveGrating {}
 impl AnalysisGhostFocus for ReflectiveGrating {}
 impl AnalysisEnergy for ReflectiveGrating {
@@ -196,27 +197,29 @@ impl AnalysisRayTrace for ReflectiveGrating {
             return Ok(LightResult::default());
         };
         if let LightData::Geometric(mut rays) = data.clone() {
-            let Ok(Proptype::I32(diffraction_order)) =
-                self.node_attr.get_property("diffraction order")
+            let Proptype::I32(diffraction_order) =
+                self.node_attr.get_property("diffraction order")?.clone()
             else {
                 return Err(OpossumError::Analysis(
                     "cannot read diffraction order".into(),
                 ));
             };
-            let Ok(Proptype::LinearDensity(line_density)) =
-                self.node_attr.get_property("line density")
+            let Proptype::LinearDensity(line_density) =
+                self.node_attr.get_property("line density")?.clone()
             else {
                 return Err(OpossumError::Analysis("cannot read line density".into()));
             };
 
             let diffracted = if let Some(iso) = self.effective_iso() {
+                let surf = self.get_surface_mut(inport);
+                surf.set_isometry(&iso);
                 let grating_vector =
                     2. * PI * line_density.value * iso.transform_vector_f64(&Vector3::x());
                 let mut diffracted_rays = rays.diffract_on_periodic_surface(
-                    &Plane::new(&iso),
+                    surf,
                     &refr_index_vaccuum(),
                     grating_vector,
-                    diffraction_order,
+                    &diffraction_order,
                 )?;
 
                 if let Some(aperture) = self.ports().aperture(&PortType::Input, inport) {
@@ -249,6 +252,9 @@ impl OpticNode for ReflectiveGrating {
     fn node_attr_mut(&mut self) -> &mut NodeAttr {
         &mut self.node_attr
     }
+    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
+        &mut self.surface
+    }
 }
 
 #[cfg(test)]
diff --git a/opossum/src/nodes/source.rs b/opossum/src/nodes/source.rs
index d35ccf5af5dae5d14f3c6311af3321692c066630..e7a11e527b583932df921076030b59b3ab85eace 100644
--- a/opossum/src/nodes/source.rs
+++ b/opossum/src/nodes/source.rs
@@ -14,12 +14,12 @@ use crate::{
     light_result::{LightRays, LightResult},
     lightdata::LightData,
     millimeter,
-    optic_node::{Alignable, OpticNode},
+    optic_node::{Alignable, OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     properties::Proptype,
     ray::Ray,
     rays::Rays,
-    surface::{hit_map::HitMap, OpticalSurface, Plane, Surface},
+    surface::{hit_map::HitMap, OpticalSurface, Plane},
     utils::{geom_transformation::Isometry, EnumProxy},
 };
 use std::{collections::HashMap, fmt::Debug};
@@ -171,6 +171,9 @@ impl OpticNode for Source {
         maps.insert("out1".to_string(), self.surface.hit_map().to_owned());
         maps
     }
+    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
+        &mut self.surface
+    }
 }
 
 impl Dottable for Source {
@@ -178,6 +181,7 @@ impl Dottable for Source {
         "slateblue"
     }
 }
+impl LIDT for Source {}
 impl Analyzable for Source {}
 impl AnalysisEnergy for Source {
     fn analyze(&mut self, _incoming_data: LightResult) -> OpmResult<LightResult> {
@@ -312,23 +316,10 @@ impl AnalysisGhostFocus for Source {
                 "no location for surface defined. Aborting".into(),
             ));
         }
-        // let outgoing = AnalysisRayTrace::analyze(
-        //     self,
-        //     light_rays_to_light_result(incoming_data),
-        //     &RayTraceConfig::default(),
-        // )?;
+
         let mut out_light_rays = LightRays::default();
         out_light_rays.insert("out1".into(), rays);
         Ok(out_light_rays)
-
-        // let outgoing = LightResult::from([("out1".into(), LightData::Geometric(rays))]);
-        // light_result_to_light_rays(outgoing)
-    }
-}
-
-impl Surface for Source {
-    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        &mut self.surface
     }
 }
 
diff --git a/opossum/src/nodes/spectrometer.rs b/opossum/src/nodes/spectrometer.rs
index 2b4b53786a9fa83a3b1d9f8ce64c4ff970fda817..08071af3b2f3cbfa445477751e1f05716ee9e0bc 100644
--- a/opossum/src/nodes/spectrometer.rs
+++ b/opossum/src/nodes/spectrometer.rs
@@ -14,13 +14,13 @@ use crate::{
     light_result::LightResult,
     lightdata::LightData,
     nanometer,
-    optic_node::OpticNode,
+    optic_node::{OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     plottable::{PlotArgs, PlotParameters, PlotSeries, PlotType, Plottable},
     properties::{Properties, Proptype},
     rays::Rays,
     reporting::node_report::NodeReport,
-    surface::{OpticalSurface, Plane, Surface},
+    surface::{OpticalSurface, Plane},
     utils::geom_transformation::Isometry,
 };
 use std::fmt::{Debug, Display};
@@ -213,10 +213,8 @@ impl OpticNode for Spectrometer {
         self.light_data = None;
         self.surface.reset_hit_map();
     }
-}
-impl Surface for Spectrometer {
     fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
+        &mut self.surface
     }
 }
 
@@ -245,6 +243,7 @@ impl Dottable for Spectrometer {
         "lightseagreen"
     }
 }
+impl LIDT for Spectrometer {}
 impl Analyzable for Spectrometer {}
 impl AnalysisGhostFocus for Spectrometer {}
 impl AnalysisEnergy for Spectrometer {
diff --git a/opossum/src/nodes/spot_diagram.rs b/opossum/src/nodes/spot_diagram.rs
index 3fcbeedabaca5bca8e2dff436dc75b661940e909..ca9b4e673edfd48efb57deb2d5ded9b8b6d3a8d0 100644
--- a/opossum/src/nodes/spot_diagram.rs
+++ b/opossum/src/nodes/spot_diagram.rs
@@ -19,13 +19,13 @@ use crate::{
     light_result::{LightRays, LightResult},
     lightdata::LightData,
     nanometer,
-    optic_node::{Alignable, OpticNode},
+    optic_node::{Alignable, OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     plottable::{AxLims, PlotArgs, PlotData, PlotParameters, PlotSeries, PlotType, Plottable},
     properties::{Properties, Proptype},
     rays::Rays,
     reporting::node_report::NodeReport,
-    surface::{hit_map::HitMap, OpticalSurface, Plane, Surface},
+    surface::{hit_map::HitMap, OpticalSurface, Plane},
     utils::{
         geom_transformation::Isometry,
         unit_format::{
@@ -96,12 +96,6 @@ impl SpotDiagram {
         sd
     }
 }
-impl Surface for SpotDiagram {
-    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        &mut self.surface
-    }
-}
-
 impl Alignable for SpotDiagram {}
 
 impl OpticNode for SpotDiagram {
@@ -190,6 +184,9 @@ impl OpticNode for SpotDiagram {
         self.light_data = None;
         self.surface.reset_hit_map();
     }
+    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
+        &mut self.surface
+    }
 }
 
 impl Dottable for SpotDiagram {
@@ -197,6 +194,7 @@ impl Dottable for SpotDiagram {
         "darkorange"
     }
 }
+impl LIDT for SpotDiagram {}
 impl Analyzable for SpotDiagram {}
 impl AnalysisGhostFocus for SpotDiagram {
     fn analyze(
diff --git a/opossum/src/nodes/thin_mirror.rs b/opossum/src/nodes/thin_mirror.rs
index d2bd80373967167a21d8a3e8ce7883abb4714b91..d89897d8ff4e61a69372dbce38e069b3a51634bb 100644
--- a/opossum/src/nodes/thin_mirror.rs
+++ b/opossum/src/nodes/thin_mirror.rs
@@ -12,10 +12,11 @@ use crate::{
     light_result::LightResult,
     lightdata::LightData,
     millimeter,
-    optic_node::{Alignable, OpticNode},
+    optic_node::{Alignable, OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     properties::Proptype,
-    surface::{OpticalSurface, Plane, Sphere, Surface},
+    surface::{OpticalSurface, Plane, Sphere},
+    utils::geom_transformation::Isometry,
 };
 use num::Zero;
 use uom::si::f64::Length;
@@ -36,6 +37,7 @@ use uom::si::f64::Length;
 ///   - `curvature`
 pub struct ThinMirror {
     node_attr: NodeAttr,
+    surface: OpticalSurface,
 }
 impl Default for ThinMirror {
     /// Create a thin mirror with a flat surface.
@@ -60,7 +62,11 @@ impl Default for ThinMirror {
             .unwrap();
         ports.add(&PortType::Output, "reflected").unwrap();
         node_attr.set_ports(ports);
-        Self { node_attr }
+
+        Self {
+            node_attr,
+            surface: OpticalSurface::new(Box::new(Plane::new(&Isometry::identity()))),
+        }
     }
 }
 impl ThinMirror {
@@ -89,6 +95,7 @@ impl ThinMirror {
             ));
         }
         self.node_attr.set_property("curvature", curvature.into())?;
+        self.update_surfaces()?;
         Ok(self)
     }
 }
@@ -99,6 +106,17 @@ impl OpticNode for ThinMirror {
     fn node_attr_mut(&mut self) -> &mut NodeAttr {
         &mut self.node_attr
     }
+    fn update_surfaces(&mut self) -> OpmResult<()> {
+        let Ok(Proptype::Length(roc)) = self.node_attr.get_property("curvature") else {
+            return Err(OpossumError::Analysis("cannot read curvature".into()));
+        };
+        self.surface = if roc.is_infinite() {
+            OpticalSurface::new(Box::new(Plane::new(&Isometry::identity())))
+        } else {
+            OpticalSurface::new(Box::new(Sphere::new(*roc, &Isometry::identity())?))
+        };
+        Ok(())
+    }
     #[cfg(feature = "bevy")]
     fn mesh(&self) -> Mesh {
         #[allow(clippy::cast_possible_truncation)]
@@ -118,11 +136,8 @@ impl OpticNode for ThinMirror {
             mesh
         }
     }
-}
-
-impl Surface for ThinMirror {
     fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
+        &mut self.surface
     }
 }
 
@@ -133,6 +148,7 @@ impl Dottable for ThinMirror {
         "aliceblue"
     }
 }
+impl LIDT for ThinMirror {}
 impl Analyzable for ThinMirror {}
 impl AnalysisGhostFocus for ThinMirror {}
 impl AnalysisEnergy for ThinMirror {
@@ -163,23 +179,17 @@ impl AnalysisRayTrace for ThinMirror {
             return Ok(LightResult::default());
         };
         if let LightData::Geometric(mut rays) = data.clone() {
-            let Ok(Proptype::Length(roc)) = self.node_attr.get_property("curvature") else {
-                return Err(OpossumError::Analysis("curvature".into()));
-            };
             let reflected = if let Some(iso) = self.effective_iso() {
-                let mut surface = if roc.is_infinite() {
-                    OpticalSurface::new(Box::new(Plane::new(&iso)))
-                } else {
-                    OpticalSurface::new(Box::new(Sphere::new(*roc, &iso)?))
-                };
-                surface.set_coating(
-                    self.node_attr()
-                        .ports()
-                        .coating(&PortType::Input, "input")
-                        .unwrap()
-                        .clone(),
-                );
-                let mut reflected_rays = rays.refract_on_surface(&mut surface, None)?;
+                let coating = self
+                    .node_attr()
+                    .ports()
+                    .coating(&PortType::Input, "input")
+                    .unwrap()
+                    .clone();
+                let surface = self.get_surface_mut("");
+                surface.set_isometry(&iso);
+                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, &iso)?;
                     reflected_rays.invalidate_by_threshold_energy(config.min_energy_per_ray())?;
diff --git a/opossum/src/nodes/wavefront.rs b/opossum/src/nodes/wavefront.rs
index adc2f5451d4214a7b0208c7b0531f5e53f64bf07..b0c2d53a101c16b05f0b998261197043aea2757d 100644
--- a/opossum/src/nodes/wavefront.rs
+++ b/opossum/src/nodes/wavefront.rs
@@ -16,12 +16,12 @@ use crate::{
     light_result::LightResult,
     lightdata::LightData,
     nanometer,
-    optic_node::{Alignable, OpticNode},
+    optic_node::{Alignable, OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     plottable::{AxLims, PlotArgs, PlotData, PlotParameters, PlotSeries, PlotType, Plottable},
     properties::{Properties, Proptype},
     reporting::node_report::NodeReport,
-    surface::{OpticalSurface, Plane, Surface},
+    surface::{OpticalSurface, Plane},
     utils::{
         geom_transformation::Isometry,
         griddata::{create_linspace_axes, interpolate_3d_scatter_data},
@@ -269,6 +269,9 @@ impl OpticNode for WaveFront {
         self.light_data = None;
         self.surface.reset_hit_map();
     }
+    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
+        &mut self.surface
+    }
 }
 impl From<WaveFrontData> for Proptype {
     fn from(value: WaveFrontData) -> Self {
@@ -280,11 +283,8 @@ impl Dottable for WaveFront {
         "goldenrod1"
     }
 }
-impl Surface for WaveFront {
-    fn get_surface_mut(&mut self, _surf_name: &str) -> &mut OpticalSurface {
-        todo!()
-    }
-}
+
+impl LIDT for WaveFront {}
 impl Analyzable for WaveFront {}
 impl AnalysisGhostFocus for WaveFront {}
 impl AnalysisEnergy for WaveFront {
diff --git a/opossum/src/nodes/wedge/analysis_ghostfocus.rs b/opossum/src/nodes/wedge/analysis_ghostfocus.rs
index a6d09454069fa985c9b0c3d963f26146b9e4d46c..ea419308449dd5ce96673b2fe59dc00dc38dfd9c 100644
--- a/opossum/src/nodes/wedge/analysis_ghostfocus.rs
+++ b/opossum/src/nodes/wedge/analysis_ghostfocus.rs
@@ -27,9 +27,10 @@ impl AnalysisGhostFocus for Wedge {
         let in_port = &self.ports().names(&PortType::Input)[0];
         let out_port = &self.ports().names(&PortType::Output)[0];
 
-        let Some(incoming_rays) = incoming_data.get(in_port) else {
-            return Ok(LightRays::default());
-        };
+        let mut rays_bundle = incoming_data
+            .get(in_port)
+            .map_or_else(Vec::<Rays>::new, std::clone::Clone::clone);
+
         let (eff_iso, refri, center_thickness, wedge) =
             self.get_node_attributes_ray_trace(&self.node_attr)?;
         let thickness_iso: Isometry = Isometry::new_along_z(center_thickness)?;
@@ -53,8 +54,6 @@ impl AnalysisGhostFocus for Wedge {
             )?;
         };
 
-        let mut rays_bundle = incoming_rays.clone();
-
         self.enter_through_surface(
             &mut rays_bundle,
             &AnalyzerType::GhostFocus(config.clone()),
diff --git a/opossum/src/nodes/wedge/mod.rs b/opossum/src/nodes/wedge/mod.rs
index ac949d8cec60bbecf37051a4d6bea71910cd764a..3cf846050a79bb1b4b752642d0cfbf6d9aae1dba 100644
--- a/opossum/src/nodes/wedge/mod.rs
+++ b/opossum/src/nodes/wedge/mod.rs
@@ -6,11 +6,11 @@ use crate::{
     dottable::Dottable,
     error::OpmResult,
     millimeter,
-    optic_node::{Alignable, OpticNode},
+    optic_node::{Alignable, OpticNode, LIDT},
     optic_ports::{OpticPorts, PortType},
     rays::Rays,
     refractive_index::{RefrIndexConst, RefractiveIndex, RefractiveIndexType},
-    surface::{hit_map::HitMap, OpticalSurface, Plane, Surface},
+    surface::{hit_map::HitMap, OpticalSurface, Plane},
     utils::{geom_transformation::Isometry, EnumProxy},
 };
 use num::Zero;
@@ -124,16 +124,6 @@ impl Wedge {
     }
 }
 
-impl Surface for Wedge {
-    fn get_surface_mut(&mut self, surf_name: &str) -> &mut OpticalSurface {
-        if surf_name == "front" {
-            &mut self.front_surf
-        } else {
-            &mut self.rear_surf
-        }
-    }
-}
-
 impl OpticNode for Wedge {
     fn reset_data(&mut self) {
         self.front_surf.set_backwards_rays_cache(Vec::<Rays>::new());
@@ -156,6 +146,13 @@ impl OpticNode for Wedge {
     fn node_attr_mut(&mut self) -> &mut NodeAttr {
         &mut self.node_attr
     }
+    fn get_surface_mut(&mut self, surf_name: &str) -> &mut OpticalSurface {
+        if surf_name == "front" {
+            &mut self.front_surf
+        } else {
+            &mut self.rear_surf
+        }
+    }
 }
 
 impl Alignable for Wedge {}
@@ -166,6 +163,7 @@ impl Dottable for Wedge {
     }
 }
 impl Analyzable for Wedge {}
+impl LIDT for Wedge {}
 
 #[cfg(test)]
 mod test {
diff --git a/opossum/src/opm_document.rs b/opossum/src/opm_document.rs
index fe35297117df7aafd79924cf2b95b76a3e8a126b..43d0473c59d1d93e0e56b7f9981becd10b57b09d 100644
--- a/opossum/src/opm_document.rs
+++ b/opossum/src/opm_document.rs
@@ -138,6 +138,7 @@ mod test {
         assert_eq!(document.opm_file_version, env!("OPM_FILE_VERSION"));
         assert!(document.analyzers.is_empty());
     }
+
     #[test]
     fn from_file() {
         let result =
diff --git a/opossum/src/optic_node.rs b/opossum/src/optic_node.rs
index 225492e4605a065de0fbec5de377d3996b7ddbc9..7e0f02454da0099b912ef365810a91205353c282 100644
--- a/opossum/src/optic_node.rs
+++ b/opossum/src/optic_node.rs
@@ -8,18 +8,19 @@ use petgraph::stable_graph::NodeIndex;
 use uom::si::f64::{Angle, Length};
 
 use crate::{
+    analyzers::Analyzable,
     aperture::Aperture,
     coatings::CoatingType,
     dottable::Dottable,
     error::{OpmResult, OpossumError},
     lightdata::LightData,
-    nodes::{NodeAttr, NodeGroup, NodeReference},
+    nodes::{fluence_detector::Fluence, NodeAttr, NodeGroup, NodeReference},
     optic_ports::{OpticPorts, PortType},
     optic_senery_rsc::SceneryResources,
     properties::{Properties, Proptype},
     refractive_index::RefractiveIndexType,
     reporting::node_report::NodeReport,
-    surface::hit_map::HitMap,
+    surface::{hit_map::HitMap, OpticalSurface},
     utils::geom_transformation::Isometry,
 };
 use core::fmt::Debug;
@@ -134,8 +135,29 @@ pub trait OpticNode: Dottable {
     /// # Errors
     /// This function will return an error if the overwritten function generates an error.
     fn after_deserialization_hook(&mut self) -> OpmResult<()> {
+        self.update_lidt();
+        self.update_surfaces()?;
         Ok(())
     }
+    ///update the surfaces of this node after deserialization
+    /// # Errors
+    /// this function might error in a non-default implementation
+    fn update_surfaces(&mut self) -> OpmResult<()> {
+        Ok(())
+    }
+    ///updates the lidt of the optical surfaces after deserialization
+    fn update_lidt(&mut self) {
+        let lidt = *self.node_attr().lidt();
+        let in_ports = self.ports().names(&PortType::Input);
+        let out_ports = self.ports().names(&PortType::Output);
+
+        for port_name in &in_ports {
+            self.get_surface_mut(port_name).set_lidt(lidt);
+        }
+        for port_name in &out_ports {
+            self.get_surface_mut(port_name).set_lidt(lidt);
+        }
+    }
     /// Return a downcasted mutable reference of a [`NodeReference`].
     ///
     /// # Errors
@@ -230,6 +252,7 @@ pub trait OpticNode: Dottable {
         node_attr_mut.set_ports(node_attributes.ports().clone());
 
         node_attr_mut.set_uuid(node_attributes.uuid());
+        node_attr_mut.set_lidt(node_attributes.lidt());
     }
     /// Get the node type of this [`OpticNode`]
     fn node_type(&self) -> String {
@@ -309,6 +332,9 @@ pub trait OpticNode: Dottable {
             |conf| conf.borrow().ambient_refr_index.clone(),
         )
     }
+
+    ///returns a mutable reference to an optical surface
+    fn get_surface_mut(&mut self, surf_name: &str) -> &mut OpticalSurface;
 }
 impl Debug for dyn OpticNode {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
@@ -361,3 +387,22 @@ pub trait Alignable: OpticNode + Sized {
         self
     }
 }
+
+///trait to define an LIDT for a node
+pub trait LIDT: OpticNode + Analyzable + Sized {
+    ///sets an LIDT value for all surfaces of this node
+    #[must_use]
+    fn with_lidt(mut self, lidt: Fluence) -> Self {
+        let in_ports = self.ports().names(&PortType::Input);
+        let out_ports = self.ports().names(&PortType::Output);
+
+        for port_name in &in_ports {
+            self.get_surface_mut(port_name).set_lidt(lidt);
+        }
+        for port_name in &out_ports {
+            self.get_surface_mut(port_name).set_lidt(lidt);
+        }
+        self.node_attr_mut().set_lidt(&lidt);
+        self
+    }
+}
diff --git a/opossum/src/ray.rs b/opossum/src/ray.rs
index 7fc28160d2554394e36757f49fb5bf0aa846e1a8..4d8b2a9898a0bcf445829330ae3534e8a06119b7 100644
--- a/opossum/src/ray.rs
+++ b/opossum/src/ray.rs
@@ -17,7 +17,7 @@ use crate::{
     joule, meter,
     nodes::FilterType,
     spectrum::Spectrum,
-    surface::{GeoSurface, OpticalSurface},
+    surface::OpticalSurface,
     utils::geom_transformation::Isometry,
 };
 
@@ -368,7 +368,7 @@ impl Ray {
     /// This function panics if the diffraction order cannot be converted to f64
     pub fn diffract_on_periodic_surface(
         &mut self,
-        s: &dyn GeoSurface,
+        s: &OpticalSurface,
         n2: f64,
         grating_vector: Vector3<f64>,
         diffraction_order: &i32,
@@ -378,7 +378,9 @@ impl Ray {
                 "the refractive index must be >=1.0 and finite".into(),
             ));
         }
-        if let Some((intersection_point, surface_normal)) = s.calc_intersect_and_normal(self) {
+        if let Some((intersection_point, surface_normal)) =
+            s.geo_surface().calc_intersect_and_normal(self)
+        {
             let surface_normal = surface_normal.normalize();
 
             // get correctly normalized k vector of ray
@@ -403,6 +405,7 @@ impl Ray {
                 self.refractive_index * meter!((pos_in_m - intersection_in_m).norm());
             //then add additional phase shift due to lateral displacement from the grating origin
             let dist_from_origin = s
+                .geo_surface()
                 .isometry()
                 .inverse_transform_point_f64(&intersection_in_m)
                 .x;
diff --git a/opossum/src/rays.rs b/opossum/src/rays.rs
index 33f2c4d8aeef7753a8b2b2f034692c48d4e04d78..7a23a091915f5c49729f3e133d2864941572d28f 100644
--- a/opossum/src/rays.rs
+++ b/opossum/src/rays.rs
@@ -18,7 +18,7 @@ use crate::{
     refractive_index::RefractiveIndexType,
     spectral_distribution::SpectralDistribution,
     spectrum::Spectrum,
-    surface::{GeoSurface, OpticalSurface},
+    surface::OpticalSurface,
     utils::{
         filter_data::{get_min_max_filter_nonfinite, get_unique_finite_values},
         geom_transformation::Isometry,
@@ -834,7 +834,7 @@ impl Rays {
     /// This function only propagates errors of contained functions.
     pub fn diffract_on_periodic_surface(
         &mut self,
-        surface: &dyn GeoSurface,
+        surface: &OpticalSurface,
         refractive_index: &RefractiveIndexType,
         grating_vector: Vector3<f64>,
         diffraction_order: &i32,
diff --git a/opossum/src/surface/hit_map.rs b/opossum/src/surface/hit_map.rs
index e3baf612db4eefcd0e839d808704293d0884549f..e7c835b39fa45ffa97609e271dbc7e2b782e56a8 100644
--- a/opossum/src/surface/hit_map.rs
+++ b/opossum/src/surface/hit_map.rs
@@ -95,6 +95,11 @@ impl RaysHitMap {
         let mut energy = DVector::<f64>::zeros(self.hit_map.len());
         let mut energy_in_ray_bundle = 0.;
 
+        if self.hit_map.len() < 3 {
+            warn!("Too few points on hitmap to calculate fluence!");
+            return Ok(None);
+        }
+
         for (row, p) in self.hit_map.iter().enumerate() {
             pos_in_cm[(row, 0)] = p.0.x.get::<centimeter>();
             pos_in_cm[(row, 1)] = p.0.y.get::<centimeter>();
@@ -211,19 +216,6 @@ impl HitMap {
         &self.critical_fluence
     }
 
-    // pub fn get_critical_fluences(&self) -> OpmResult<Vec<(Uuid, usize, Fluence, Fluence)>>{
-    //     let max_fluence = J_per_cm2!(0.02);
-    //     let mut critical_positions = Vec::<(Uuid, usize, Fluence, Fluence)>::new();
-    //     for (bounce, bounced_hit_map) in self.hit_map.iter().enumerate(){
-    //         for (uuid, rays_hit_map) in &bounced_hit_map.hit_map{
-    //             if let Some((_vdat, _x_lim, _y_lim, average_fluence, peak_fluence)) = rays_hit_map.calc_fluence(max_fluence)?{
-    //                 critical_positions.push((uuid.clone(), bounce, average_fluence, peak_fluence));
-    //             }
-    //         }
-    //     }
-    //     Ok(critical_positions)
-    // }
-
     ///stores a critical fluence in a hitmap
     pub fn add_critical_fluence(&mut self, uuid: &Uuid, rays_hist_pos: usize, fluence: Fluence) {
         self.critical_fluence
diff --git a/opossum/src/surface/mod.rs b/opossum/src/surface/mod.rs
index c174fcad696d5e90bbb3f606cd0868326ac53e8f..5377bd20449254cd0de52ec11b53f3cecc4c735e 100644
--- a/opossum/src/surface/mod.rs
+++ b/opossum/src/surface/mod.rs
@@ -62,9 +62,3 @@ impl Debug for dyn GeoSurface {
         write!(f, "Surface")
     }
 }
-
-///Surface trait
-pub trait Surface {
-    ///returns a mutable reference to the surface with a given name
-    fn get_surface_mut(&mut self, surf_name: &str) -> &mut OpticalSurface;
-}
diff --git a/opossum/src/surface/optical_surface.rs b/opossum/src/surface/optical_surface.rs
index 55670cedd78771b14f2b376590ca1e1d8040423d..9000b04b3303aadea0c245134a2a1ef535a823d1 100644
--- a/opossum/src/surface/optical_surface.rs
+++ b/opossum/src/surface/optical_surface.rs
@@ -1,3 +1,4 @@
+use log::warn;
 use nalgebra::Point3;
 use uom::si::f64::{Energy, Length};
 use uuid::Uuid;
@@ -30,7 +31,7 @@ impl Default for OpticalSurface {
             backward_rays_cache: Vec::<Rays>::new(),
             forward_rays_cache: Vec::<Rays>::new(),
             hit_map: HitMap::default(),
-            lidt: J_per_cm2!(0.1),
+            lidt: J_per_cm2!(1.0),
         }
     }
 }
@@ -56,7 +57,7 @@ impl OpticalSurface {
             backward_rays_cache: Vec::<Rays>::new(),
             forward_rays_cache: Vec::<Rays>::new(),
             hit_map: HitMap::default(),
-            lidt: J_per_cm2!(0.1),
+            lidt: J_per_cm2!(1.0),
         }
     }
     /// Returns a reference to the coating of this [`OpticalSurface`].
@@ -147,4 +148,18 @@ impl OpticalSurface {
         }
         Ok(())
     }
+
+    ///returns a reference to the lidt value of this [`OpticalSurface`]
+    #[must_use]
+    pub fn lidt(&self) -> &Fluence {
+        &self.lidt
+    }
+    ///set the lidt of this [`OpticalSurface`]
+    pub fn set_lidt(&mut self, lidt: Fluence) {
+        if lidt.is_sign_negative() || !lidt.is_normal() {
+            warn!("LIDT values mut be > 0 and finite! Using default value of 1 J/cm²");
+            return;
+        }
+        self.lidt = lidt;
+    }
 }