From 0b0aba84b4581d75842bfa37f4da338f9a835b9b Mon Sep 17 00:00:00 2001 From: alconley Date: Sun, 17 Nov 2024 21:55:10 -0500 Subject: [PATCH] modified: src/histoer/cuts.rs modified: src/histoer/histo1d/plot_settings.rs modified: src/histoer/histo2d/context_menu.rs modified: src/histoer/histo2d/histogram2d.rs modified: src/histoer/histo2d/keybinds.rs modified: src/histoer/histo2d/plot_settings.rs modified: src/histoer/histogrammer.rs modified: src/histogram_scripter/histogram_script.rs modified: src/histogram_scripter/manual_histogram_scripts.rs --- src/histoer/cuts.rs | 75 +- src/histoer/histo1d/plot_settings.rs | 2 +- src/histoer/histo2d/context_menu.rs | 60 ++ src/histoer/histo2d/histogram2d.rs | 3 +- src/histoer/histo2d/keybinds.rs | 4 +- src/histoer/histo2d/plot_settings.rs | 34 +- src/histoer/histogrammer.rs | 7 +- src/histogram_scripter/histogram_script.rs | 769 +++++++++--------- .../manual_histogram_scripts.rs | 58 +- 9 files changed, 504 insertions(+), 508 deletions(-) diff --git a/src/histoer/cuts.rs b/src/histoer/cuts.rs index 91699e0..4e734b9 100644 --- a/src/histoer/cuts.rs +++ b/src/histoer/cuts.rs @@ -20,10 +20,6 @@ impl Default for Cut { } impl Cut { - pub fn new_2d_cut(&self) -> Self { - Cut::Cut2D(Cut2D::default()) - } - // Method to check if a cut is valid for a specific row in the DataFrame pub fn valid(&self, df: &DataFrame, row_idx: usize) -> bool { match self { @@ -34,34 +30,6 @@ impl Cut { } } - pub fn menu_button(&mut self, ui: &mut egui::Ui) { - match self { - Cut::Cut1D(cut1d) => cut1d.menu_button(ui), - Cut::Cut2D(cut2d) => cut2d.menu_button(ui), - } - } - - pub fn draw(&mut self, plot_ui: &mut egui_plot::PlotUi) { - match self { - Cut::Cut1D(_) => {} - Cut::Cut2D(cut2d) => cut2d.polygon.draw(plot_ui), - } - } - - pub fn interactive_response(&mut self, plot_response: &egui_plot::PlotResponse<()>) { - match self { - Cut::Cut1D(_) => {} - Cut::Cut2D(cut2d) => cut2d.polygon.handle_interactions(plot_response), - } - } - - pub fn is_dragging(&self) -> bool { - match self { - Cut::Cut1D(_) => false, - Cut::Cut2D(cut2d) => cut2d.polygon.is_dragging, - } - } - pub fn table_row(&mut self, row: &mut egui_extras::TableRow<'_, '_>) { match self { Cut::Cut1D(cut1d) => cut1d.table_row(row), @@ -96,23 +64,18 @@ impl Default for Cut2D { impl Cut2D { pub fn ui(&mut self, ui: &mut egui::Ui) { - ui.add( - egui::TextEdit::singleline(&mut self.polygon.name) - .hint_text("Name") - .clip_text(false), - ); - - ui.add( - egui::TextEdit::singleline(&mut self.x_column) - .hint_text("X Column Name") - .clip_text(false), - ); + if ui.button("Load").clicked() { + if let Err(e) = self.load_cut_from_json() { + log::error!("Error loading cut: {:?}", e); + } + } - ui.add( - egui::TextEdit::singleline(&mut self.y_column) - .hint_text("Y Column Name") - .clip_text(false), - ); + if ui.button("Save").clicked() { + if let Err(e) = self.save_cut_to_json() { + log::error!("Error saving cut: {:?}", e); + } + } + self.polygon.menu_button(ui); } pub fn table_row(&mut self, row: &mut egui_extras::TableRow<'_, '_>) { @@ -210,6 +173,22 @@ impl Cut2D { let polygon = self.to_geo_polygon(); polygon.contains(&point) } + + pub fn draw(&mut self, plot_ui: &mut egui_plot::PlotUi) { + self.polygon.draw(plot_ui); + } + + pub fn interactions(&mut self, plot_response: &egui_plot::PlotResponse<()>) { + self.polygon.handle_interactions(plot_response); + } + + pub fn is_dragging(&self) -> bool { + self.polygon.is_dragging + } + + pub fn is_clicking(&self) -> bool { + self.polygon.interactive_clicking + } } // Struct to hold each parsed condition diff --git a/src/histoer/histo1d/plot_settings.rs b/src/histoer/histo1d/plot_settings.rs index 25717f0..db8d955 100644 --- a/src/histoer/histo1d/plot_settings.rs +++ b/src/histoer/histo1d/plot_settings.rs @@ -30,7 +30,7 @@ impl Default for PlotSettings { } impl PlotSettings { pub fn settings_ui(&mut self, ui: &mut egui::Ui) { - self.egui_settings.menu_button(ui); + // self.egui_settings.menu_button(ui); ui.checkbox(&mut self.stats_info, "Show Statistics"); self.markers.menu_button(ui); } diff --git a/src/histoer/histo2d/context_menu.rs b/src/histoer/histo2d/context_menu.rs index d18b65e..686f93e 100644 --- a/src/histoer/histo2d/context_menu.rs +++ b/src/histoer/histo2d/context_menu.rs @@ -1,4 +1,5 @@ use super::histogram2d::Histogram2D; +use crate::histoer::cuts::Cut2D; impl Histogram2D { // Context menu for the plot (when you right-click on the plot) @@ -6,6 +7,48 @@ impl Histogram2D { self.image.menu_button(ui); self.plot_settings.settings_ui(ui, self.bins.max_count); + ui.horizontal(|ui| { + ui.heading("Cuts"); + + if ui.button("+").clicked() { + self.new_cut(); + } + }); + + ui.horizontal(|ui| { + ui.label("X: "); + ui.add( + egui::TextEdit::singleline(&mut self.plot_settings.x_column) + .hint_text("X Column Name"), + ); + }); + + ui.horizontal(|ui| { + ui.label("Y: "); + ui.add( + egui::TextEdit::singleline(&mut self.plot_settings.y_column) + .hint_text("Y Column Name"), + ); + }); + + let mut to_remove = None; + + for (index, cut) in self.plot_settings.cuts.iter_mut().enumerate() { + ui.horizontal(|ui| { + if ui.button("X").clicked() { + to_remove = Some(index); + } + + ui.separator(); + + cut.ui(ui); + }); + } + + if let Some(index) = to_remove { + self.plot_settings.cuts.remove(index); + } + ui.separator(); ui.heading("Rebin"); @@ -47,4 +90,21 @@ impl Histogram2D { } }); } + + pub fn new_cut(&mut self) { + for cut in &mut self.plot_settings.cuts { + cut.polygon.interactive_clicking = false; + cut.polygon.interactive_dragging = false; + } + + let mut cut = Cut2D { + x_column: self.plot_settings.x_column.clone(), + y_column: self.plot_settings.y_column.clone(), + ..Default::default() + }; + cut.polygon.name = format!("Cut {}", self.plot_settings.cuts.len()); + + cut.polygon.interactive_clicking = true; + self.plot_settings.cuts.push(cut); + } } diff --git a/src/histoer/histo2d/histogram2d.rs b/src/histoer/histo2d/histogram2d.rs index bf536c9..b5df1b9 100644 --- a/src/histoer/histo2d/histogram2d.rs +++ b/src/histoer/histo2d/histogram2d.rs @@ -207,8 +207,7 @@ impl Histogram2D { self.plot_settings.draw(plot_ui); - self.plot_settings.egui_settings.allow_drag = !(self.plot_settings.cuts.is_dragging() - || self.plot_settings.projections.is_dragging()); + self.plot_settings.egui_settings.allow_drag = !self.plot_settings.projections.is_dragging(); if self.plot_settings.egui_settings.limit_scrolling { self.limit_scrolling(plot_ui); diff --git a/src/histoer/histo2d/keybinds.rs b/src/histoer/histo2d/keybinds.rs index ea7f203..139e3c1 100644 --- a/src/histoer/histo2d/keybinds.rs +++ b/src/histoer/histo2d/keybinds.rs @@ -9,8 +9,8 @@ impl Histogram2D { } if ui.input(|i| i.key_pressed(egui::Key::C)) { - self.plot_settings.cuts.new_2d_cut(); - } + self.new_cut(); + }; if ui.input(|i| i.key_pressed(egui::Key::X)) { self.plot_settings.projections.add_x_projection = diff --git a/src/histoer/histo2d/plot_settings.rs b/src/histoer/histo2d/plot_settings.rs index a3f180f..1385afa 100644 --- a/src/histoer/histo2d/plot_settings.rs +++ b/src/histoer/histo2d/plot_settings.rs @@ -1,5 +1,5 @@ // use crate::cutter::Cut::HistogramCut; -use crate::histoer::cuts::Cut; +use crate::histoer::cuts::Cut2D; use crate::egui_plot_stuff::egui_plot_settings::EguiPlotSettings; @@ -11,7 +11,9 @@ pub struct PlotSettings { #[serde(skip)] pub cursor_position: Option, pub egui_settings: EguiPlotSettings, - pub cuts: Cut, + pub x_column: String, + pub y_column: String, + pub cuts: Vec, pub stats_info: bool, pub colormap: ColorMap, pub colormap_options: ColormapOptions, @@ -29,7 +31,9 @@ impl Default for PlotSettings { PlotSettings { cursor_position: None, egui_settings: EguiPlotSettings::default(), - cuts: Cut::default(), + x_column: String::new(), + y_column: String::new(), + cuts: vec![], stats_info: false, colormap: ColorMap::default(), colormap_options: ColormapOptions::default(), @@ -53,32 +57,30 @@ impl PlotSettings { ui.separator(); ui.checkbox(&mut self.stats_info, "Show Statitics"); - self.egui_settings.menu_button(ui); + // self.egui_settings.menu_button(ui); ui.separator(); self.projections.menu_button(ui); ui.separator(); - - self.cuts.menu_button(ui); - - // if any Cut are active temp disable double clicking to reset - // self.egui_settings.allow_double_click_reset = !self - // .Cut - // .Cut - // .iter() - // .any(|cut| cut.polygon.interactive_clicking); } pub fn draw(&mut self, plot_ui: &mut egui_plot::PlotUi) { - self.cuts.draw(plot_ui); + for cut in &mut self.cuts { + cut.draw(plot_ui); + } self.projections.draw(plot_ui); } pub fn interactive_response(&mut self, plot_response: &egui_plot::PlotResponse<()>) { self.projections.interactive_dragging(plot_response); - self.cuts.interactive_response(plot_response); + + for cut in &mut self.cuts { + self.egui_settings.allow_drag = !cut.is_dragging(); + self.egui_settings.allow_double_click_reset = !cut.is_clicking(); + cut.interactions(plot_response); + } } pub fn progress_ui(&mut self, ui: &mut egui::Ui) { @@ -91,6 +93,4 @@ impl PlotSettings { ); } } - - // pub fn keybinds(&mut self, ui: &mut egui::Ui) {} } diff --git a/src/histoer/histogrammer.rs b/src/histoer/histogrammer.rs index 1133fc0..16bdbf0 100644 --- a/src/histoer/histogrammer.rs +++ b/src/histoer/histogrammer.rs @@ -532,10 +532,10 @@ impl Histogrammer { } }); - for (hist, _meta) in &hist2d_map { + for (hist, meta) in &hist2d_map { let mut hist = hist.lock().unwrap(); - // hist.plot_settings.cuts.x_column = meta.x_column_name.clone(); - // hist.plot_settings.cuts.y_column = meta.y_column_name.clone(); + hist.plot_settings.x_column = meta.x_column_name.clone(); + hist.plot_settings.y_column = meta.y_column_name.clone(); hist.plot_settings.recalculate_image = true; } @@ -667,7 +667,6 @@ impl Histogrammer { self.tree.ui(&mut self.behavior, ui); } - /// Main UI function to display the histogram selection panel and other components pub fn side_panel_ui(&mut self, ui: &mut egui::Ui) { self.behavior.ui(ui); ui.separator(); diff --git a/src/histogram_scripter/histogram_script.rs b/src/histogram_scripter/histogram_script.rs index b0c12c8..d624011 100644 --- a/src/histogram_scripter/histogram_script.rs +++ b/src/histogram_scripter/histogram_script.rs @@ -48,7 +48,6 @@ impl HistogramScript { } } - // Helper function to check if a histogram with the given name already exists fn histogram_exists(&self, name: &str) -> bool { self.hist_configs.iter().any(|config| match config { HistoConfig::Histo1D(hist) => hist.name == name, @@ -56,14 +55,12 @@ impl HistogramScript { }) } - // Helper function to check if a column with the given alias already exists fn column_exists(&self, alias: &str) -> bool { self.new_columns .iter() .any(|(_, col_alias)| col_alias == alias) } - // Sorting logic based on the selected SortOrder and reverse_sort flag fn sort_histograms(&mut self) { match self.sort_order { SortOrder::Name => { @@ -102,7 +99,77 @@ impl HistogramScript { } } - pub fn ui(&mut self, ui: &mut egui::Ui) { + fn column_creation_ui(&mut self, ui: &mut egui::Ui) { + ui.horizontal(|ui| { + ui.heading("Column Creation"); + + if ui.button("+").clicked() { + self.new_columns.push(("".to_string(), "".to_string())); + } + + ui.separator(); + + if ui.button("Remove All").clicked() { + self.new_columns.clear(); + } + }); + + if !self.new_columns.is_empty() { + let mut indices_to_remove_column = Vec::new(); + + TableBuilder::new(ui) + .id_salt("new_columns") + .column(Column::auto()) // expression + .column(Column::auto()) // alias + .column(Column::remainder()) // Actions + .striped(true) + .vscroll(false) + .header(20.0, |mut header| { + header.col(|ui| { + ui.label("Alias"); + }); + header.col(|ui| { + ui.label("Expression"); + }); + }) + .body(|mut body| { + for (index, (expression, alias)) in self.new_columns.iter_mut().enumerate() { + body.row(18.0, |mut row| { + row.col(|ui| { + ui.add( + egui::TextEdit::singleline(alias) + .hint_text("Alias") + .clip_text(false), + ); + }); + + row.col(|ui| { + ui.add( + egui::TextEdit::singleline(expression) + .hint_text("Expression") + .clip_text(false), + ); + }); + + row.col(|ui| { + ui.horizontal(|ui| { + if ui.button("X").clicked() { + indices_to_remove_column.push(index); + } + }); + }); + }); + } + }); + + // Remove indices in reverse order to prevent shifting issues + for &index in indices_to_remove_column.iter().rev() { + self.new_columns.remove(index); + } + } + } + + fn histogram_script_ui(&mut self, ui: &mut egui::Ui) { ui.label("Custom Histogram Scripts"); ui.horizontal(|ui| { if ui.button("SE-SPS").clicked() { @@ -145,426 +212,349 @@ impl HistogramScript { } } }); + } - ui.separator(); - - // Add header controls + fn cut_ui(&mut self, ui: &mut egui::Ui) { + ui.horizontal(|ui| { + ui.heading("Cuts"); - egui::ScrollArea::vertical().show(ui, |ui| { - ui.horizontal(|ui| { - ui.heading("Column Creation"); + if ui.button("+1D").clicked() { + // Add logic to create a new 1D cut and add it to `self.cuts` + // For example: + self.cuts.push(Cut::Cut1D(Cut1D::new("", ""))); + } - if ui.button("+").clicked() { - self.new_columns.push(("".to_string(), "".to_string())); + if ui.button("+2D").clicked() { + // Create a new instance of Cut2D and attempt to load it from a JSON file + let mut new_cut2d = Cut2D::default(); + if new_cut2d.load_cut_from_json().is_ok() { + // If successfully loaded, add it to the cuts vector as a Cuts::Cut2D variant + self.cuts.push(Cut::Cut2D(new_cut2d)); + } else { + log::error!("Failed to load 2D cut from file."); } + } - ui.separator(); + ui.separator(); - if ui.button("Remove All").clicked() { - self.new_columns.clear(); + if ui.button("Remove All").clicked() { + self.cuts.clear(); + for hist_config in &mut self.hist_configs { + match hist_config { + HistoConfig::Histo1D(hist1d) => { + hist1d.cuts.clear(); + } + HistoConfig::Histo2D(hist2d) => { + hist2d.cuts.clear(); + } + } } - }); + } + }); + + if !self.cuts.is_empty() { + let mut indices_to_remove_cut = Vec::new(); - if !self.new_columns.is_empty() { - let mut indices_to_remove_column = Vec::new(); + let mut cuts_1d = Vec::new(); + let mut cuts_2d = Vec::new(); + self.cuts + .iter_mut() + .enumerate() + .for_each(|(i, cut)| match cut { + Cut::Cut1D(_) => cuts_1d.push((i, cut)), + Cut::Cut2D(cut2d) => cuts_2d.push((i, cut2d)), + }); + + // Render 1D Cuts Table + if !cuts_1d.is_empty() { + ui.label("1D Cuts"); TableBuilder::new(ui) - .id_salt("new_columns") - .column(Column::auto()) // expression - .column(Column::auto()) // alias + .id_salt("cuts_1d_table") + .column(Column::auto()) // Name + .column(Column::auto()) // Expression .column(Column::remainder()) // Actions .striped(true) .vscroll(false) .header(20.0, |mut header| { header.col(|ui| { - ui.label("Alias"); + ui.label("Name"); }); header.col(|ui| { - ui.label("Expression"); + ui.label("Operation(s)"); }); }) .body(|mut body| { - for (index, (expression, alias)) in self.new_columns.iter_mut().enumerate() - { + for (index, cut1d) in cuts_1d { body.row(18.0, |mut row| { + cut1d.table_row(&mut row); row.col(|ui| { - ui.add( - egui::TextEdit::singleline(alias) - .hint_text("Alias") - .clip_text(false), - ); - }); - - row.col(|ui| { - ui.add( - egui::TextEdit::singleline(expression) - .hint_text("Expression") - .clip_text(false), - ); + ui.horizontal(|ui| { + if ui.button("X").clicked() { + indices_to_remove_cut.push(index); + } + }); }); + }); + } + }); + } + if !cuts_2d.is_empty() { + ui.label("2D Cuts"); + TableBuilder::new(ui) + .id_salt("cuts_2d_table") + .column(Column::auto()) // Name + .column(Column::auto()) // X Column + .column(Column::auto()) // Y Column + .column(Column::remainder()) // Actions + .striped(true) + .vscroll(false) + .header(20.0, |mut header| { + header.col(|ui| { + ui.label("Name"); + }); + header.col(|ui| { + ui.label("X Column"); + }); + header.col(|ui| { + ui.label("Y Column"); + }); + }) + .body(|mut body| { + for (index, cut2d) in cuts_2d { + body.row(18.0, |mut row| { + cut2d.table_row(&mut row); row.col(|ui| { ui.horizontal(|ui| { if ui.button("X").clicked() { - indices_to_remove_column.push(index); + indices_to_remove_cut.push(index); } }); }); }); } }); + } - // Remove indices in reverse order to prevent shifting issues - for &index in indices_to_remove_column.iter().rev() { - self.new_columns.remove(index); - } + for &index in indices_to_remove_cut.iter().rev() { + self.cuts.remove(index); } + } + } - ui.separator(); + fn histogram_ui(&mut self, ui: &mut egui::Ui) { + ui.horizontal(|ui| { + ui.heading("Histograms"); + + if ui.button("+1D").clicked() { + self.hist_configs.push(HistoConfig::Histo1D(Histo1DConfig { + name: "".to_string(), + column_name: "".to_string(), + range: (0.0, 4096.0), + bins: 512, + cuts: vec![], + calculate: true, + })); + } - ui.horizontal(|ui| { - ui.heading("Cuts"); + if ui.button("+2D").clicked() { + self.hist_configs.push(HistoConfig::Histo2D(Histo2DConfig { + name: "".to_string(), + x_column_name: "".to_string(), + y_column_name: "".to_string(), + x_range: (0.0, 4096.0), + y_range: (0.0, 4096.0), + bins: (512, 512), + cuts: vec![], + calculate: true, + })); + } - if ui.button("+1D").clicked() { - // Add logic to create a new 1D cut and add it to `self.cuts` - // For example: - self.cuts.push(Cut::Cut1D(Cut1D::new("", ""))); - } + ui.separator(); - if ui.button("+2D").clicked() { - // Create a new instance of Cut2D and attempt to load it from a JSON file - let mut new_cut2d = Cut2D::default(); - if new_cut2d.load_cut_from_json().is_ok() { - // If successfully loaded, add it to the cuts vector as a Cuts::Cut2D variant - self.cuts.push(Cut::Cut2D(new_cut2d)); - } else { - log::error!("Failed to load 2D cut from file."); - } - } + if ui.button("Remove All").clicked() { + self.hist_configs.clear(); + } + }); - ui.separator(); + // Sorting controls + ui.horizontal(|ui| { + ui.label("Sort by:"); + if ui.button("Name").clicked() { + self.sort_order = SortOrder::Name; + self.reverse_sort = !self.reverse_sort; + self.sort_histograms(); + } + if ui.button("Column").clicked() { + self.sort_order = SortOrder::Column; + self.reverse_sort = !self.reverse_sort; + self.sort_histograms(); + } + if ui.button("Type").clicked() { + self.sort_order = SortOrder::Type; + self.reverse_sort = !self.reverse_sort; + self.sort_histograms(); + } + }); - if ui.button("Remove All").clicked() { - self.cuts.clear(); - for hist_config in &mut self.hist_configs { - match hist_config { - HistoConfig::Histo1D(hist1d) => { - hist1d.cuts.clear(); + let mut indices_to_remove = Vec::new(); + + // Create the table + TableBuilder::new(ui) + .id_salt("hist_configs") + .column(Column::auto()) // Type + .column(Column::auto()) // Name + .column(Column::auto()) // Columns + .column(Column::auto()) // Ranges + .column(Column::auto()) // Bins + .column(Column::auto()) // cuts + .column(Column::remainder()) // Actions + .striped(true) + .vscroll(false) + .header(20.0, |mut header| { + header.col(|ui| { + ui.label(" # "); + }); + header.col(|ui| { + ui.label("Name"); + }); + header.col(|ui| { + ui.label("Column(s)"); + }); + header.col(|ui| { + ui.label("Range(s)"); + }); + header.col(|ui| { + ui.label("Bins"); + }); + header.col(|ui| { + ui.label("Cuts"); + }); + header.col(|ui| { + ui.label("Actions"); + }); + }) + .body(|mut body| { + for (index, config) in self.hist_configs.iter_mut().enumerate() { + body.row(18.0, |mut row| { + row.col(|ui| match config { + HistoConfig::Histo1D(_) => { + ui.label(format!("{index}")); } - HistoConfig::Histo2D(hist2d) => { - hist2d.cuts.clear(); + HistoConfig::Histo2D(_) => { + ui.label(format!("{index}")); } - } - } - } - }); - - if !self.cuts.is_empty() { - let mut indices_to_remove_cut = Vec::new(); - - let mut cuts_1d = Vec::new(); - let mut cuts_2d = Vec::new(); - - self.cuts - .iter_mut() - .enumerate() - .for_each(|(i, cut)| match cut { - Cut::Cut1D(_) => cuts_1d.push((i, cut)), - Cut::Cut2D(cut2d) => cuts_2d.push((i, cut2d)), - }); + }); - // Render 1D Cuts Table - if !cuts_1d.is_empty() { - ui.label("1D Cuts"); - TableBuilder::new(ui) - .id_salt("cuts_1d_table") - .column(Column::auto()) // Name - .column(Column::auto()) // Expression - .column(Column::remainder()) // Actions - .striped(true) - .vscroll(false) - .header(20.0, |mut header| { - header.col(|ui| { - ui.label("Name"); - }); - header.col(|ui| { - ui.label("Operation(s)"); - }); - }) - .body(|mut body| { - for (index, cut1d) in cuts_1d { - body.row(18.0, |mut row| { - cut1d.table_row(&mut row); - row.col(|ui| { - ui.horizontal(|ui| { - if ui.button("X").clicked() { - indices_to_remove_cut.push(index); - } - }); - }); - }); + row.col(|ui| match config { + HistoConfig::Histo1D(hist) => { + ui.add( + egui::TextEdit::singleline(&mut hist.name) + .hint_text("Name") + .clip_text(false), + ); } - }); - } - if !cuts_2d.is_empty() { - ui.label("2D Cuts"); - TableBuilder::new(ui) - .id_salt("cuts_2d_table") - .column(Column::auto()) // Name - .column(Column::auto()) // X Column - .column(Column::auto()) // Y Column - .column(Column::remainder()) // Actions - .striped(true) - .vscroll(false) - .header(20.0, |mut header| { - header.col(|ui| { - ui.label("Name"); - }); - header.col(|ui| { - ui.label("X Column"); - }); - header.col(|ui| { - ui.label("Y Column"); - }); - }) - .body(|mut body| { - for (index, cut2d) in cuts_2d { - body.row(18.0, |mut row| { - cut2d.table_row(&mut row); - row.col(|ui| { - ui.horizontal(|ui| { - if ui.button("X").clicked() { - indices_to_remove_cut.push(index); - } - }); - }); - }); + HistoConfig::Histo2D(hist) => { + ui.add( + egui::TextEdit::singleline(&mut hist.name) + .hint_text("Name") + .clip_text(false), + ); } }); - } - - for &index in indices_to_remove_cut.iter().rev() { - self.cuts.remove(index); - } - } - - ui.separator(); - - ui.horizontal(|ui| { - ui.heading("Histograms"); - - if ui.button("+1D").clicked() { - self.hist_configs.push(HistoConfig::Histo1D(Histo1DConfig { - name: "".to_string(), - column_name: "".to_string(), - range: (0.0, 4096.0), - bins: 512, - cuts: vec![], - calculate: true, - })); - } - - if ui.button("+2D").clicked() { - self.hist_configs.push(HistoConfig::Histo2D(Histo2DConfig { - name: "".to_string(), - x_column_name: "".to_string(), - y_column_name: "".to_string(), - x_range: (0.0, 4096.0), - y_range: (0.0, 4096.0), - bins: (512, 512), - cuts: vec![], - calculate: true, - })); - } - - ui.separator(); - - if ui.button("Remove All").clicked() { - self.hist_configs.clear(); - } - }); - - // Sorting controls - ui.horizontal(|ui| { - ui.label("Sort by:"); - if ui.button("Name").clicked() { - self.sort_order = SortOrder::Name; - self.reverse_sort = !self.reverse_sort; - self.sort_histograms(); - } - if ui.button("Column").clicked() { - self.sort_order = SortOrder::Column; - self.reverse_sort = !self.reverse_sort; - self.sort_histograms(); - } - if ui.button("Type").clicked() { - self.sort_order = SortOrder::Type; - self.reverse_sort = !self.reverse_sort; - self.sort_histograms(); - } - }); - - let mut indices_to_remove = Vec::new(); - - // Create the table - TableBuilder::new(ui) - .id_salt("hist_configs") - .column(Column::auto()) // Type - .column(Column::auto()) // Name - .column(Column::auto()) // Columns - .column(Column::auto()) // Ranges - .column(Column::auto()) // Bins - .column(Column::auto()) // cuts - .column(Column::remainder()) // Actions - .striped(true) - .vscroll(false) - .header(20.0, |mut header| { - header.col(|ui| { - ui.label(" # "); - }); - header.col(|ui| { - ui.label("Name"); - }); - header.col(|ui| { - ui.label("Column(s)"); - }); - header.col(|ui| { - ui.label("Range(s)"); - }); - header.col(|ui| { - ui.label("Bins"); - }); - header.col(|ui| { - ui.label("Cuts"); - }); - header.col(|ui| { - ui.label("Actions"); - }); - }) - .body(|mut body| { - for (index, config) in self.hist_configs.iter_mut().enumerate() { - body.row(18.0, |mut row| { - row.col(|ui| match config { - HistoConfig::Histo1D(_) => { - ui.label(format!("{index}")); - } - HistoConfig::Histo2D(_) => { - ui.label(format!("{index}")); - } - }); - row.col(|ui| match config { - HistoConfig::Histo1D(hist) => { + row.col(|ui| match config { + HistoConfig::Histo1D(hist) => { + ui.add( + egui::TextEdit::singleline(&mut hist.column_name) + .hint_text("Column Name") + .clip_text(false), + ); + } + HistoConfig::Histo2D(hist) => { + ui.vertical(|ui| { ui.add( - egui::TextEdit::singleline(&mut hist.name) - .hint_text("Name") + egui::TextEdit::singleline(&mut hist.x_column_name) + .hint_text("X Column Name") .clip_text(false), ); - } - - HistoConfig::Histo2D(hist) => { ui.add( - egui::TextEdit::singleline(&mut hist.name) - .hint_text("Name") + egui::TextEdit::singleline(&mut hist.y_column_name) + .hint_text("Y Column Name") .clip_text(false), ); - } - }); + }); + } + }); - row.col(|ui| match config { - HistoConfig::Histo1D(hist) => { + row.col(|ui| match config { + HistoConfig::Histo1D(hist) => { + ui.horizontal(|ui| { ui.add( - egui::TextEdit::singleline(&mut hist.column_name) - .hint_text("Column Name") - .clip_text(false), + egui::DragValue::new(&mut hist.range.0) + .speed(0.1) + .prefix("(") + .suffix(","), ); - } - HistoConfig::Histo2D(hist) => { - ui.vertical(|ui| { + ui.add( + egui::DragValue::new(&mut hist.range.1) + .speed(0.1) + .prefix(" ") + .suffix(")"), + ); + }); + } + HistoConfig::Histo2D(hist) => { + ui.vertical(|ui| { + ui.horizontal(|ui| { ui.add( - egui::TextEdit::singleline(&mut hist.x_column_name) - .hint_text("X Column Name") - .clip_text(false), + egui::DragValue::new(&mut hist.x_range.0) + .speed(1.0) + .prefix("(") + .suffix(","), ); ui.add( - egui::TextEdit::singleline(&mut hist.y_column_name) - .hint_text("Y Column Name") - .clip_text(false), + egui::DragValue::new(&mut hist.x_range.1) + .speed(1.0) + .prefix(" ") + .suffix(")"), ); }); - } - }); - - row.col(|ui| match config { - HistoConfig::Histo1D(hist) => { ui.horizontal(|ui| { ui.add( - egui::DragValue::new(&mut hist.range.0) - .speed(0.1) + egui::DragValue::new(&mut hist.y_range.0) + .speed(1.0) .prefix("(") .suffix(","), ); ui.add( - egui::DragValue::new(&mut hist.range.1) - .speed(0.1) + egui::DragValue::new(&mut hist.y_range.1) + .speed(1.0) .prefix(" ") .suffix(")"), ); }); - } - HistoConfig::Histo2D(hist) => { - ui.vertical(|ui| { - ui.horizontal(|ui| { - ui.add( - egui::DragValue::new(&mut hist.x_range.0) - .speed(1.0) - .prefix("(") - .suffix(","), - ); - ui.add( - egui::DragValue::new(&mut hist.x_range.1) - .speed(1.0) - .prefix(" ") - .suffix(")"), - ); - }); - ui.horizontal(|ui| { - ui.add( - egui::DragValue::new(&mut hist.y_range.0) - .speed(1.0) - .prefix("(") - .suffix(","), - ); - ui.add( - egui::DragValue::new(&mut hist.y_range.1) - .speed(1.0) - .prefix(" ") - .suffix(")"), - ); - }); - }); - } - }); + }); + } + }); - row.col(|ui| match config { - HistoConfig::Histo1D(hist) => { - ui.add(egui::DragValue::new(&mut hist.bins).speed(1)); - } - HistoConfig::Histo2D(hist) => { - ui.vertical(|ui| { - ui.add(egui::DragValue::new(&mut hist.bins.0).speed(1)); - ui.add(egui::DragValue::new(&mut hist.bins.1).speed(1)); - }); - } - }); + row.col(|ui| match config { + HistoConfig::Histo1D(hist) => { + ui.add(egui::DragValue::new(&mut hist.bins).speed(1)); + } + HistoConfig::Histo2D(hist) => { + ui.vertical(|ui| { + ui.add(egui::DragValue::new(&mut hist.bins.0).speed(1)); + ui.add(egui::DragValue::new(&mut hist.bins.1).speed(1)); + }); + } + }); - row.col(|ui| match config { - HistoConfig::Histo1D(hist) => { - egui::ComboBox::from_id_salt(format!( - "cut_select_1d_{}", - index - )) + row.col(|ui| match config { + HistoConfig::Histo1D(hist) => { + egui::ComboBox::from_id_salt(format!("cut_select_1d_{}", index)) .selected_text("Select cuts") .width(ui.available_width()) .show_ui(ui, |ui| { @@ -608,12 +598,9 @@ impl HistogramScript { } } }); - } - HistoConfig::Histo2D(hist) => { - egui::ComboBox::from_id_salt(format!( - "cut_select_2d_{}", - index - )) + } + HistoConfig::Histo2D(hist) => { + egui::ComboBox::from_id_salt(format!("cut_select_2d_{}", index)) .selected_text("Select cuts") .width(ui.available_width()) .show_ui(ui, |ui| { @@ -657,38 +644,35 @@ impl HistogramScript { } } }); - } - }); + } + }); - row.col(|ui| { - ui.horizontal(|ui| { - match config { - HistoConfig::Histo1D(hist) => { - ui.checkbox(&mut hist.calculate, ""); - } - HistoConfig::Histo2D(hist) => { - ui.checkbox(&mut hist.calculate, ""); - } + row.col(|ui| { + ui.horizontal(|ui| { + match config { + HistoConfig::Histo1D(hist) => { + ui.checkbox(&mut hist.calculate, ""); + } + HistoConfig::Histo2D(hist) => { + ui.checkbox(&mut hist.calculate, ""); } + } - ui.separator(); + ui.separator(); - if ui.button("X").clicked() { - indices_to_remove.push(index); - } - }); + if ui.button("X").clicked() { + indices_to_remove.push(index); + } }); }); - } - }); - - // Remove indices in reverse order to prevent shifting issues - for &index in indices_to_remove.iter().rev() { - self.hist_configs.remove(index); - } - }); + }); + } + }); - self.verify_cuts(); + // Remove indices in reverse order to prevent shifting issues + for &index in indices_to_remove.iter().rev() { + self.hist_configs.remove(index); + } } fn verify_cuts(&mut self) { @@ -729,7 +713,27 @@ impl HistogramScript { } } - pub fn save_histogram_script(&self) -> io::Result<()> { + pub fn ui(&mut self, ui: &mut egui::Ui) { + self.histogram_script_ui(ui); + + ui.separator(); + + egui::ScrollArea::vertical().show(ui, |ui| { + self.column_creation_ui(ui); + + ui.separator(); + + self.cut_ui(ui); + + ui.separator(); + + self.histogram_ui(ui); + }); + + self.verify_cuts(); + } + + fn save_histogram_script(&self) -> io::Result<()> { if let Some(path) = FileDialog::new() .set_title("Save Histogram Script") .save_file() @@ -743,8 +747,7 @@ impl HistogramScript { } } - // Function to load histogram configuration from a JSON file - pub fn load_histogram_script(&mut self) -> io::Result<()> { + fn load_histogram_script(&mut self) -> io::Result<()> { if let Some(path) = FileDialog::new() .set_title("Load Histogram Script") .pick_file() diff --git a/src/histogram_scripter/manual_histogram_scripts.rs b/src/histogram_scripter/manual_histogram_scripts.rs index c69e1ec..4c3cded 100644 --- a/src/histogram_scripter/manual_histogram_scripts.rs +++ b/src/histogram_scripter/manual_histogram_scripts.rs @@ -1,5 +1,8 @@ use super::histogram_script::HistoConfig; -use crate::histoer::histogrammer::{Histo1DConfig, Histo2DConfig}; +use crate::histoer::{ + // cuts::Cut1D, + histogrammer::{Histo1DConfig, Histo2DConfig}, +}; use polars::prelude::*; use std::f64::consts::PI; @@ -51,27 +54,6 @@ pub fn get_column_names_from_lazyframe(lazyframe: &LazyFrame) -> Vec { #[allow(clippy::all)] pub fn sps_histograms() -> (Vec<(String, String)>, Vec) { - // (col("DelayFrontRightEnergy") + col("DelayFrontLeftEnergy") / lit(2.0)).alias("DelayFrontAverageEnergy"), - // (col("DelayBackRightEnergy") + col("DelayBackLeftEnergy") / lit(2.0)).alias("DelayBackAverageEnergy"), - // (col("DelayFrontLeftTime") - col("AnodeFrontTime")).alias("DelayFrontLeftTime_AnodeFrontTime"), - // (col("DelayFrontRightTime") - col("AnodeFrontTime")).alias("DelayFrontRightTime_AnodeFrontTime"), - // (col("DelayBackLeftTime") - col("AnodeFrontTime")).alias("DelayBackLeftTime_AnodeFrontTime"), - // (col("DelayBackRightTime") - col("AnodeFrontTime")).alias("DelayBackRightTime_AnodeFrontTime"), - // (col("DelayFrontLeftTime") - col("AnodeBackTime")).alias("DelayFrontLeftTime_AnodeBackTime"), - // (col("DelayFrontRightTime") - col("AnodeBackTime")).alias("DelayFrontRightTime_AnodeBackTime"), - // (col("DelayBackLeftTime") - col("AnodeBackTime")).alias("DelayBackLeftTime_AnodeBackTime"), - // (col("DelayBackRightTime") - col("AnodeBackTime")).alias("DelayBackRightTime_AnodeBackTime"), - // (col("AnodeFrontTime") - col("AnodeBackTime")).alias("AnodeFrontTime_AnodeBackTime"), - // (col("AnodeBackTime") - col("AnodeFrontTime")).alias("AnodeBackTime_AnodeFrontTime"), - // (col("AnodeFrontTime") - col("ScintLeftTime")).alias("AnodeFrontTime_ScintLeftTime"), - // (col("AnodeBackTime") - col("ScintLeftTime")).alias("AnodeBackTime_ScintLeftTime"), - // (col("DelayFrontLeftTime") - col("ScintLeftTime")).alias("DelayFrontLeftTime_ScintLeftTime"), - // (col("DelayFrontRightTime") - col("ScintLeftTime")).alias("DelayFrontRightTime_ScintLeftTime"), - // (col("DelayBackLeftTime") - col("ScintLeftTime")).alias("DelayBackLeftTime_ScintLeftTime"), - // (col("DelayBackRightTime") - col("ScintLeftTime")).alias("DelayBackRightTime_ScintLeftTime"), - // (col("ScintRightTime") - col("ScintLeftTime")).alias("ScintRightTime_ScintLeftTime"), - // (lit(-0.013139237615)*col("Xavg")*col("Xavg") + lit(-13.80004977)*col("Xavg") + lit(9790.048149635)).alias("XavgEnergyCalibrated") - let mut new_columns = vec![]; new_columns.push(("( DelayFrontRightEnergy + DelayFrontLeftEnergy ) / 2.0".into(), "DelayFrontAverageEnergy".into())); new_columns.push(("( DelayBackRightEnergy + DelayBackLeftEnergy ) / 2.0".into(), "DelayBackAverageEnergy".into())); @@ -93,6 +75,9 @@ pub fn sps_histograms() -> (Vec<(String, String)>, Vec) { new_columns.push(("DelayBackRightTime - ScintLeftTime".into(), "DelayBackRightTime_ScintLeftTime".into())); new_columns.push(("ScintRightTime - ScintLeftTime".into(), "ScintRightTime_ScintLeftTime".into())); + // let x1_only1plane_cut = Cut1D::new("Only X1 Plane", "X1 != -1e6 && X2 == -1e6"); + // let x2_only1plane_cut = Cut1D::new("Only X2 Plane", "X2 != -1e6 && X1 == -1e6"); + // let bothplanes_cut = Cut1D::new("Both Planes", "X2 != -1e6 && X1 != -1e6"); let mut histograms = vec![]; @@ -146,35 +131,6 @@ pub fn sps_histograms() -> (Vec<(String, String)>, Vec) { (new_columns, histograms) } /* - - let lf_sps = lf.with_columns(vec![ - (col("DelayFrontRightEnergy") + col("DelayFrontLeftEnergy") / lit(2.0)).alias("DelayFrontAverageEnergy"), - (col("DelayBackRightEnergy") + col("DelayBackLeftEnergy") / lit(2.0)).alias("DelayBackAverageEnergy"), - (col("DelayFrontLeftTime") - col("AnodeFrontTime")).alias("DelayFrontLeftTime_AnodeFrontTime"), - (col("DelayFrontRightTime") - col("AnodeFrontTime")).alias("DelayFrontRightTime_AnodeFrontTime"), - (col("DelayBackLeftTime") - col("AnodeFrontTime")).alias("DelayBackLeftTime_AnodeFrontTime"), - (col("DelayBackRightTime") - col("AnodeFrontTime")).alias("DelayBackRightTime_AnodeFrontTime"), - (col("DelayFrontLeftTime") - col("AnodeBackTime")).alias("DelayFrontLeftTime_AnodeBackTime"), - (col("DelayFrontRightTime") - col("AnodeBackTime")).alias("DelayFrontRightTime_AnodeBackTime"), - (col("DelayBackLeftTime") - col("AnodeBackTime")).alias("DelayBackLeftTime_AnodeBackTime"), - (col("DelayBackRightTime") - col("AnodeBackTime")).alias("DelayBackRightTime_AnodeBackTime"), - (col("AnodeFrontTime") - col("AnodeBackTime")).alias("AnodeFrontTime_AnodeBackTime"), - (col("AnodeBackTime") - col("AnodeFrontTime")).alias("AnodeBackTime_AnodeFrontTime"), - (col("AnodeFrontTime") - col("ScintLeftTime")).alias("AnodeFrontTime_ScintLeftTime"), - (col("AnodeBackTime") - col("ScintLeftTime")).alias("AnodeBackTime_ScintLeftTime"), - (col("DelayFrontLeftTime") - col("ScintLeftTime")).alias("DelayFrontLeftTime_ScintLeftTime"), - (col("DelayFrontRightTime") - col("ScintLeftTime")).alias("DelayFrontRightTime_ScintLeftTime"), - (col("DelayBackLeftTime") - col("ScintLeftTime")).alias("DelayBackLeftTime_ScintLeftTime"), - (col("DelayBackRightTime") - col("ScintLeftTime")).alias("DelayBackRightTime_ScintLeftTime"), - (col("ScintRightTime") - col("ScintLeftTime")).alias("ScintRightTime_ScintLeftTime"), - // (lit(-0.013139237615)*col("Xavg")*col("Xavg") + lit(-13.80004977)*col("Xavg") + lit(9790.048149635)).alias("XavgEnergyCalibrated") - ]); - - let lf_bothplanes = lf_sps.clone().filter(col("X1").neq(lit(-1e6))).filter(col("X2").neq(lit(-1e6))); - let lf_only_x1_plane = lf_sps.clone().filter(col("X1").neq(lit(-1e6))).filter(col("X2").eq(lit(-1e6))); - let lf_only_x2_plane = lf_sps.clone().filter(col("X2").neq(lit(-1e6))).filter(col("X1").eq(lit(-1e6))); - - // // // //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.... // Delay lines vs Focal plane histograms let lf_time_rel_backanode = lf_sps.clone().filter(col("AnodeBackTime").neq(lit(-1e6))).filter(col("ScintLeftTime").neq(lit(-1e6)));