From 4cfa29334a94b85f0598bbc4e8d84830e1116fcf Mon Sep 17 00:00:00 2001 From: "y.zobus" <y.zobus@gsi.de> Date: Wed, 16 Oct 2024 10:50:23 +0200 Subject: [PATCH] feat: :sparkles: added different colors to bounces in hitmap plots --- opossum/examples/ghost_focus.rs | 2 +- opossum/src/ray.rs | 2 +- opossum/src/reporting/analysis_report.rs | 2 +- opossum/src/surface/hit_map.rs | 100 ++++++++++++++--------- opossum/src/surface/optical_surface.rs | 4 +- 5 files changed, 66 insertions(+), 44 deletions(-) diff --git a/opossum/examples/ghost_focus.rs b/opossum/examples/ghost_focus.rs index dd856e5f..9313760d 100644 --- a/opossum/examples/ghost_focus.rs +++ b/opossum/examples/ghost_focus.rs @@ -45,7 +45,7 @@ fn main() -> OpmResult<()> { .with_tilt(degree!(0.0, 5.0, 0.0))?; wedge.set_coating(&PortType::Input, "front", &CoatingType::Fresnel)?; wedge.set_coating(&PortType::Input, "front", &CoatingType::Fresnel)?; - let i_w=scenery.add_node(wedge)?; + 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))?; diff --git a/opossum/src/ray.rs b/opossum/src/ray.rs index 15b53509..8e29c9a1 100644 --- a/opossum/src/ray.rs +++ b/opossum/src/ray.rs @@ -448,7 +448,7 @@ impl Ray { self.refractive_index = n2; self.number_of_refractions += 1; // save on hit map of surface - os.add_to_hit_map((intersection_point, input_energy)); + os.add_to_hit_map((intersection_point, input_energy), self.number_of_bounces); Ok(Some(reflected_ray)) } else { diff --git a/opossum/src/reporting/analysis_report.rs b/opossum/src/reporting/analysis_report.rs index d2c77d36..107d8c56 100644 --- a/opossum/src/reporting/analysis_report.rs +++ b/opossum/src/reporting/analysis_report.rs @@ -90,7 +90,7 @@ impl AnalysisReport { /// /// This information is used i.e. in the [`HtmlReport`]. pub fn set_analysis_type(&mut self, analysis_type: &str) { - self.analysis_type = analysis_type.to_owned(); + analysis_type.clone_into(&mut self.analysis_type); } } diff --git a/opossum/src/surface/hit_map.rs b/opossum/src/surface/hit_map.rs index b889f555..6aa5af55 100644 --- a/opossum/src/surface/hit_map.rs +++ b/opossum/src/surface/hit_map.rs @@ -1,12 +1,10 @@ //! Data structure for storing intersection points (and energies) of [`Rays`](crate::rays::Rays) hitting an //! [`OpticalSurface`](crate::surface::OpticalSurface). +use colorous::Color; use nalgebra::{DVector, MatrixXx2, Point2, Point3}; use plotters::style::RGBAColor; use serde::{Deserialize, Serialize}; -use uom::si::{ - f64::{Energy, Length}, - length::meter, -}; +use uom::si::f64::{Energy, Length}; use crate::{ error::OpmResult, @@ -22,20 +20,24 @@ use crate::{ /// [`OpticalSurface`](crate::surface::OpticalSurface). #[derive(Default, Debug, Clone, Serialize, Deserialize)] pub struct HitMap { - hit_map: Vec<(Point3<Length>, Energy)>, + hit_map: Vec<Vec<(Point3<Length>, Energy)>>, } impl HitMap { /// Returns a reference to the hit map of this [`HitMap`]. /// /// This function returns a vector of intersection points (with energies) of [`Rays`](crate::rays::Rays) that hit the surface. #[must_use] - pub fn hit_map(&self) -> &[(Point3<Length>, Energy)] { + pub fn hit_map(&self) -> &[Vec<(Point3<Length>, Energy)>] { &self.hit_map } /// Add intersection point (with energy) to this [`HitMap`]. /// - pub fn add_point(&mut self, hit_point: (Point3<Length>, Energy)) { - self.hit_map.push(hit_point); + pub fn add_point(&mut self, hit_point: (Point3<Length>, Energy), bounce: usize) { + if self.hit_map.len() <= bounce { + self.hit_map.push(vec![hit_point]); + } else { + self.hit_map[bounce].push(hit_point); + } } /// Reset this [`HitMap`]. /// @@ -61,22 +63,25 @@ impl Plottable for HitMap { _legend: bool, ) -> OpmResult<Option<Vec<PlotSeries>>> { //ray plot series + let mut plt_series = Vec::<PlotSeries>::with_capacity(self.hit_map.len()); + let mut xy_positions = Vec::<Vec<Point2<Length>>>::with_capacity(self.hit_map.len()); let mut x_max = f64::NEG_INFINITY; let mut y_max = f64::NEG_INFINITY; + let mut x_min = f64::INFINITY; + let mut y_min = f64::INFINITY; + + for hit_map in &self.hit_map { + let mut xy_pos = Vec::<Point2<Length>>::with_capacity(hit_map.len()); + for p in hit_map { + xy_pos.push(Point2::new(p.0.x, p.0.y)); - let xy_pos: Vec<Point2<Length>> = self - .hit_map - .iter() - .map(|p| Point2::new(p.0.x, p.0.y)) - .collect(); - x_max = xy_pos - .iter() - .map(|p| p.x.get::<meter>()) - .fold(x_max, |arg0, x| if x.abs() > arg0 { x.abs() } else { arg0 }); - y_max = xy_pos - .iter() - .map(|p| p.y.get::<meter>()) - .fold(y_max, |arg0, y| if y.abs() > arg0 { y.abs() } else { arg0 }); + x_max = x_max.max(p.0.x.value); + y_max = y_max.max(p.0.y.value); + x_min = x_min.min(p.0.x.value); + y_min = y_min.min(p.0.y.value); + } + xy_positions.push(xy_pos); + } let x_exponent = get_exponent_for_base_unit_in_e3_steps(x_max); let y_exponent = get_exponent_for_base_unit_in_e3_steps(y_max); let y_prefix = get_prefix_for_base_unit(y_max); @@ -85,29 +90,46 @@ impl Plottable for HitMap { plt_type.set_plot_param(&PlotArgs::XLabel(format!("x position ({y_prefix}m)")))?; plt_type.set_plot_param(&PlotArgs::YLabel(format!("y position ({x_prefix}m)")))?; - let mut plt_series = Vec::<PlotSeries>::with_capacity(1); - let x_vals = xy_pos - .iter() - .map(|p| get_unit_value_as_length_with_format_by_exponent(p.x, x_exponent)) - .collect::<Vec<f64>>(); - let y_vals = xy_pos - .iter() - .map(|p| get_unit_value_as_length_with_format_by_exponent(p.y, y_exponent)) - .collect::<Vec<f64>>(); + for (i, xy_pos) in xy_positions.iter().enumerate() { + let x_vals = xy_pos + .iter() + .map(|p| get_unit_value_as_length_with_format_by_exponent(p.x, x_exponent)) + .collect::<Vec<f64>>(); + let y_vals = xy_pos + .iter() + .map(|p| get_unit_value_as_length_with_format_by_exponent(p.y, y_exponent)) + .collect::<Vec<f64>>(); + + let data = PlotData::Dim2 { + xy_data: MatrixXx2::from_columns(&[ + DVector::from_vec(x_vals), + DVector::from_vec(y_vals), + ]), + }; - let data = PlotData::Dim2 { - xy_data: MatrixXx2::from_columns(&[ - DVector::from_vec(x_vals), - DVector::from_vec(y_vals), - ]), - }; + let gradient = colorous::TURBO; + let c = if self.hit_map.len() == 1 { + Color { r: 255, g: 0, b: 0 } + } else if self.hit_map.len() > 10 { + gradient.eval_rational(i, self.hit_map.len()) + } else { + colorous::CATEGORY10[i] + }; + let label = format!("Bounce: {i}"); + plt_series.push(PlotSeries::new( + &data, + RGBAColor(c.r, c.g, c.b, 1.), + Some(label), + )); + } - plt_series.push(PlotSeries::new(&data, RGBAColor(255, 0, 0, 1.), None)); x_max *= f64::powi(10., -x_exponent); y_max *= f64::powi(10., -y_exponent); + x_min *= f64::powi(10., -x_exponent); + y_min *= f64::powi(10., -y_exponent); - let x_limits = AxLims::create_useful_axlims(-x_max * 1.1, x_max * 1.1); - let y_limits = AxLims::create_useful_axlims(-y_max * 1.1, y_max * 1.1); + let x_limits = AxLims::create_useful_axlims(x_min * 1.1, x_max * 1.1); + let y_limits = AxLims::create_useful_axlims(y_min * 1.1, y_max * 1.1); plt_type.set_plot_param(&PlotArgs::XLim(x_limits))?; plt_type.set_plot_param(&PlotArgs::YLim(y_limits))?; diff --git a/opossum/src/surface/optical_surface.rs b/opossum/src/surface/optical_surface.rs index 8798b1d0..9cf78e72 100644 --- a/opossum/src/surface/optical_surface.rs +++ b/opossum/src/surface/optical_surface.rs @@ -93,8 +93,8 @@ impl OpticalSurface { } /// Add intersection point (with energy) to hit map. /// - pub fn add_to_hit_map(&mut self, hit_point: (Point3<Length>, Energy)) { - self.hit_map.add_point(hit_point); + pub fn add_to_hit_map(&mut self, hit_point: (Point3<Length>, Energy), bounce: usize) { + self.hit_map.add_point(hit_point, bounce); } /// Reset hit map of this [`OpticalSurface`]. pub fn reset_hit_map(&mut self) { -- GitLab