From bad96c4bc0aaf655b2514614eec38b8030b60df4 Mon Sep 17 00:00:00 2001 From: alconley Date: Mon, 11 Nov 2024 20:32:18 -0500 Subject: [PATCH] modified: src/cutter/cut_handler.rs modified: src/cutter/cuts.rs modified: src/egui_plot_stuff/colors.rs modified: src/egui_plot_stuff/egui_polygon.rs modified: src/histoer/histogrammer.rs deleted: src/histogram_scripter/configure_lazyframes.rs modified: src/histogram_scripter/histogram_script.rs modified: src/histogram_scripter/mod.rs modified: src/util/processer.rs --- src/cutter/cut_handler.rs | 12 +- src/cutter/cuts.rs | 39 ++- src/egui_plot_stuff/colors.rs | 2 +- src/egui_plot_stuff/egui_polygon.rs | 2 +- src/histoer/histogrammer.rs | 204 ++++++++++--- .../configure_lazyframes.rs | 190 ------------ src/histogram_scripter/histogram_script.rs | 282 +++++++++++++----- src/histogram_scripter/mod.rs | 2 - src/util/processer.rs | 152 +++++----- 9 files changed, 483 insertions(+), 402 deletions(-) delete mode 100644 src/histogram_scripter/configure_lazyframes.rs diff --git a/src/cutter/cut_handler.rs b/src/cutter/cut_handler.rs index 3ea6ce0..3802dbc 100644 --- a/src/cutter/cut_handler.rs +++ b/src/cutter/cut_handler.rs @@ -21,17 +21,12 @@ impl CutHandler { { let file = File::open(file_path)?; let reader = BufReader::new(file); - let mut cut: Cut = serde_json::from_reader(reader)?; - cut.selected = true; + let cut: Cut = serde_json::from_reader(reader)?; self.cuts.push(cut); } Ok(()) } - pub fn cuts_are_selected(&self) -> bool { - self.cuts.iter().any(|cut| cut.selected) - } - pub fn cut_ui(&mut self, ui: &mut egui::Ui, histogrammer: &mut Histogrammer) { ui.collapsing("Cuts", |ui| { ui.horizontal(|ui| { @@ -68,7 +63,6 @@ impl CutHandler { cut.ui(ui); ui.horizontal(|ui| { - ui.checkbox(&mut cut.selected, ""); if ui.button("🗙").clicked() { index_to_remove = Some(index); } @@ -98,9 +92,7 @@ impl CutHandler { // Iterate through all cuts and apply their respective filters. for cut in &mut self.cuts { - if cut.selected { - filtered_lf = cut.filter_lf_with_cut(&filtered_lf)?; - } + filtered_lf = cut.filter_lf_with_cut(&filtered_lf)?; } Ok(filtered_lf) diff --git a/src/cutter/cuts.rs b/src/cutter/cuts.rs index f8b9181..07b2289 100644 --- a/src/cutter/cuts.rs +++ b/src/cutter/cuts.rs @@ -7,23 +7,49 @@ use std::io::{BufReader, Write}; use crate::egui_plot_stuff::egui_polygon::EguiPolygon; -#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)] +#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, PartialEq)] pub struct Cut { pub polygon: EguiPolygon, pub x_column: String, pub y_column: String, - #[serde(skip)] - pub selected: bool, +} + +impl Default for Cut { + fn default() -> Self { + Cut { + polygon: EguiPolygon::default(), + x_column: "".to_string(), + y_column: "".to_string(), + } + } } impl Cut { pub fn ui(&mut self, ui: &mut egui::Ui) { // putting this in a grid - ui.text_edit_singleline(&mut self.x_column); + // ui.text_edit_singleline(&mut self.x_column); + + // ui.text_edit_singleline(&mut self.y_column); - ui.text_edit_singleline(&mut self.y_column); + // self.polygon.polygon_info_menu_button(ui); + + ui.add( + egui::TextEdit::singleline(&mut self.polygon.name) + .hint_text("Name") + .clip_text(false), + ); - self.polygon.polygon_info_menu_button(ui); + ui.add( + egui::TextEdit::singleline(&mut self.x_column) + .hint_text("X Column Name") + .clip_text(false), + ); + + ui.add( + egui::TextEdit::singleline(&mut self.y_column) + .hint_text("Y Column Name") + .clip_text(false), + ); } pub fn menu_button(&mut self, ui: &mut egui::Ui) { @@ -217,7 +243,6 @@ impl HistogramCuts { polygon: new_cut, x_column: "".to_string(), y_column: "".to_string(), - selected: false, }; self.cuts.push(new_cut); } diff --git a/src/egui_plot_stuff/colors.rs b/src/egui_plot_stuff/colors.rs index ec98b3c..fba2bab 100644 --- a/src/egui_plot_stuff/colors.rs +++ b/src/egui_plot_stuff/colors.rs @@ -24,7 +24,7 @@ pub const COLOR_OPTIONS: &[(Color32, &str)] = &[ (Color32::LIGHT_BLUE, "Light Blue"), ]; -#[derive(Debug, Clone, Copy, serde::Deserialize, serde::Serialize)] +#[derive(Debug, Clone, Copy, serde::Deserialize, serde::Serialize, PartialEq)] pub struct Rgb { pub r: u8, pub g: u8, diff --git a/src/egui_plot_stuff/egui_polygon.rs b/src/egui_plot_stuff/egui_polygon.rs index 9c978d7..3704d7b 100644 --- a/src/egui_plot_stuff/egui_polygon.rs +++ b/src/egui_plot_stuff/egui_polygon.rs @@ -4,7 +4,7 @@ use geo::Contains; use crate::egui_plot_stuff::colors::{Rgb, COLOR_OPTIONS}; -#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)] +#[derive(Debug, Clone, serde::Deserialize, serde::Serialize, PartialEq)] pub struct EguiPolygon { pub draw: bool, pub name_in_legend: bool, diff --git a/src/histoer/histogrammer.rs b/src/histoer/histogrammer.rs index aeda3b3..86fa440 100644 --- a/src/histoer/histogrammer.rs +++ b/src/histoer/histogrammer.rs @@ -3,6 +3,8 @@ use super::histo2d::histogram2d::Histogram2D; use super::pane::Pane; use super::tree::TreeBehavior; use crate::cutter::cut_handler::CutHandler; +use crate::cutter::cuts::Cut; + use egui_tiles::TileId; use fnv::FnvHashMap; @@ -42,6 +44,7 @@ pub struct Histo1DConfig { pub column_name: String, // Data column to fill from pub range: (f64, f64), // Range for the histogram pub bins: usize, // Number of bins + pub cuts: Vec, // Cuts for the histogram pub calculate: bool, // Whether to calculate the histogram } @@ -52,6 +55,7 @@ impl Histo1DConfig { column_name: column_name.to_string(), range, bins, + cuts: Vec::new(), calculate: true, } } @@ -65,6 +69,7 @@ pub struct Histo2DConfig { pub x_range: (f64, f64), // Range for X-axis pub y_range: (f64, f64), // Range for Y-axis pub bins: (usize, usize), // Number of bins for X and Y axes + pub cuts: Vec, // Cuts for the histogram pub calculate: bool, // Whether to calculate the histogram } @@ -84,6 +89,7 @@ impl Histo2DConfig { x_range, y_range, bins, + cuts: Vec::new(), calculate: true, } } @@ -233,52 +239,68 @@ impl Histogrammer { // Collect available column names let available_columns = self.get_column_names_from_lazyframe(&lf); - // Filter hist1d_specs and hist2d_specs to include only those marked for calculation and with existing columns - let hist1d_specs: Vec<_> = hist1d_specs - .into_iter() - .filter(|h| { - if h.calculate { - if available_columns.contains(&h.column_name) { - true - } else { - println!( - "Warning: Column '{}' does not exist for 1D histogram: '{}'. Skipping.", - h.column_name, h.name - ); - false + // Filter and validate histograms based on existing columns + let hist1d_specs: Vec<_> = hist1d_specs.into_iter().filter(|h| { + if h.calculate { + let column_exists = available_columns.contains(&h.column_name); + if !column_exists { + println!("Warning: Column '{}' does not exist for 1D histogram '{}'. Skipping.", h.column_name, h.name); + return false; + } + for cut in &h.cuts { + if !available_columns.contains(&cut.x_column) { + println!("Warning: Cut column '{}' does not exist for 1D histogram '{}'. Skipping cut.", cut.x_column, h.name); + return false; } - } else { - false } - }) - .collect(); - - let hist2d_specs: Vec<_> = hist2d_specs - .into_iter() - .filter(|h| { - if h.calculate { - let missing_columns = !available_columns.contains(&h.x_column_name) || !available_columns.contains(&h.y_column_name); - if missing_columns { - println!("Warning: Columns '{}' or '{}' do not exist for 2D histogram '{}'. Skipping.", h.x_column_name, h.y_column_name, h.name); - false - } else { - true + true + } else { + false + } + }).collect(); + + let hist2d_specs: Vec<_> = hist2d_specs.into_iter().filter(|h| { + if h.calculate { + let columns_exist = available_columns.contains(&h.x_column_name) && available_columns.contains(&h.y_column_name); + if !columns_exist { + println!("Warning: Columns '{}' or '{}' do not exist for 2D histogram '{}'. Skipping.", h.x_column_name, h.y_column_name, h.name); + return false; + } + for cut in &h.cuts { + if !available_columns.contains(&cut.x_column) || !available_columns.contains(&cut.y_column) { + println!("Warning: Cut columns '{}' or '{}' do not exist for 2D histogram '{}'. Skipping cut.", cut.x_column, cut.y_column, h.name); + return false; } - } else { - false } - }) - .collect(); + true + } else { + false + } + }).collect(); // Collect column names for the remaining histograms let mut column_names: Vec<&str> = hist1d_specs .iter() .map(|h| h.column_name.as_str()) .collect(); + + // Include columns required for cuts in both 1D and 2D histograms + for h in &hist1d_specs { + for cut in &h.cuts { + column_names.push(cut.x_column.as_str()); + } + } + for h in &hist2d_specs { column_names.push(h.x_column_name.as_str()); column_names.push(h.y_column_name.as_str()); + + for cut in &h.cuts { + column_names.push(cut.x_column.as_str()); + column_names.push(cut.y_column.as_str()); + } } + column_names.sort_unstable(); column_names.dedup(); @@ -381,17 +403,87 @@ impl Histogrammer { if let Ok(df) = lf_selected.collect() { let height = df.height(); - // Parallel filling of histograms + // // Parallel filling of histograms + // hist1d_map.par_iter().for_each(|(hist, meta)| { + // if let Ok(col_idx) = df.column(&meta.column_name) { + // if let Ok(col_values) = col_idx.f64() { + // let mut hist = hist.lock().unwrap(); + // for value in col_values.into_no_null_iter() { + // if value == -1e6 { + // continue; + // } + + // hist.fill(value); + // } + // } + // } + // }); + + // hist2d_map.par_iter().for_each(|(hist, meta)| { + // if let (Ok(x_values), Ok(y_values)) = ( + // df.column(&meta.x_column_name).and_then(|c| c.f64()), + // df.column(&meta.y_column_name).and_then(|c| c.f64()), + // ) { + // let mut hist = hist.lock().unwrap(); + // for (x, y) in x_values + // .into_no_null_iter() + // .zip(y_values.into_no_null_iter()) + // { + // if x == -1e6 || y == -1e6 { + // continue; + // } + + // hist.fill(x, y); + // } + // } + // }); + + // Parallel filling of 1D histograms hist1d_map.par_iter().for_each(|(hist, meta)| { if let Ok(col_idx) = df.column(&meta.column_name) { if let Ok(col_values) = col_idx.f64() { let mut hist = hist.lock().unwrap(); - for value in col_values.into_no_null_iter() { + + // Loop over each row, matching the row index in the DataFrame with the cut columns + for (index, value) in col_values.into_no_null_iter().enumerate() + { if value == -1e6 { continue; } - hist.fill(value); + // Track if this point passes all cuts for this histogram + let mut passes_all_cuts = true; + + // Evaluate each cut for the current point + for cut in &meta.cuts { + // Get the cut-specific column values for the current row + if let (Ok(cut_x_values), Ok(cut_y_values)) = ( + df.column(&cut.x_column).and_then(|c| c.f64()), + df.column(&cut.y_column).and_then(|c| c.f64()), + ) { + if let (Some(cut_x), Some(cut_y)) = ( + cut_x_values.get(index), + cut_y_values.get(index), + ) { + // Check if the point (cut_x, cut_y) is inside the cut polygon + if !cut.is_inside(cut_x, cut_y) { + passes_all_cuts = false; + break; + } + } else { + passes_all_cuts = false; + break; + } + } else { + passes_all_cuts = false; + break; + } + } + + // Fill histogram only if all cuts pass for this point + if passes_all_cuts { + hist.fill(value); + } } } } @@ -403,21 +495,57 @@ impl Histogrammer { df.column(&meta.y_column_name).and_then(|c| c.f64()), ) { let mut hist = hist.lock().unwrap(); - for (x, y) in x_values + + // Loop over each row, matching the row index in the DataFrame with the cut columns + for (index, (x, y)) in x_values .into_no_null_iter() .zip(y_values.into_no_null_iter()) + .enumerate() { if x == -1e6 || y == -1e6 { continue; } - hist.fill(x, y); + // Track if this point passes all cuts for this histogram + let mut passes_all_cuts = true; + + // Evaluate each cut for the current point + for cut in &meta.cuts { + // Get the cut-specific column values for the current row + if let (Ok(cut_x_values), Ok(cut_y_values)) = ( + df.column(&cut.x_column).and_then(|c| c.f64()), + df.column(&cut.y_column).and_then(|c| c.f64()), + ) { + if let (Some(cut_x), Some(cut_y)) = + (cut_x_values.get(index), cut_y_values.get(index)) + { + // Check if the point (cut_x, cut_y) is inside the cut polygon + if !cut.is_inside(cut_x, cut_y) { + passes_all_cuts = false; + break; + } + } else { + passes_all_cuts = false; + break; + } + } else { + passes_all_cuts = false; + break; + } + } + + // Fill histogram only if all cuts pass for this point + if passes_all_cuts { + hist.fill(x, y); + } } } }); - for (hist, _) 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.recalculate_image = true; } diff --git a/src/histogram_scripter/configure_lazyframes.rs b/src/histogram_scripter/configure_lazyframes.rs deleted file mode 100644 index 0063afa..0000000 --- a/src/histogram_scripter/configure_lazyframes.rs +++ /dev/null @@ -1,190 +0,0 @@ -use polars::prelude::*; -use std::collections::HashMap; - -#[derive(Default, serde::Deserialize, serde::Serialize, Clone)] -pub struct LazyFrameInfo { - pub lfs: Vec, - pub columns: Vec, -} - -#[derive(Default, serde::Deserialize, serde::Serialize, Clone)] -pub struct LazyFrames { - #[serde(skip)] - pub lfs: HashMap, - pub info: LazyFrameInfo, -} - -impl LazyFrames { - pub fn new() -> Self { - Self::default() - } - - #[allow(clippy::all)] - pub fn add_columns_to_lazyframe(&self, lf: &LazyFrame) -> LazyFrame { - let lf = lf.clone().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"), - ]); - - lf - } - - pub fn filtered_lfs(&self, lf: LazyFrame) -> HashMap { - let mut lfs = HashMap::new(); - let pid = lf - .clone() - .filter(col("ScintLeftEnergy").neq(lit(-1e6))) - .filter(col("AnodeBackEnergy").neq(lit(-1e6))); - - let lf_bothplanes = lf - .clone() - .filter(col("X1").neq(lit(-1e6))) - .filter(col("X2").neq(lit(-1e6))); - - let lf_only_x1_plane = lf - .clone() - .filter(col("X1").neq(lit(-1e6))) - .filter(col("X2").eq(lit(-1e6))); - - let lf_only_x2_plane = lf - .clone() - .filter(col("X2").neq(lit(-1e6))) - .filter(col("X1").eq(lit(-1e6))); - - lfs.insert("Raw".to_string(), lf); - lfs.insert("BothPlanes".to_string(), lf_bothplanes); - lfs.insert("OnlyX1Plane".to_string(), lf_only_x1_plane); - lfs.insert("OnlyX2Plane".to_string(), lf_only_x2_plane); - lfs.insert("PID".to_string(), pid); - - lfs - } - - #[allow(clippy::all)] - pub fn main_column_names(&self) -> Vec { - let main_sps_columns = vec![ - "AnodeFrontEnergy", - "AnodeFrontShort", - "AnodeFrontTime", - "AnodeBackEnergy", - "AnodeBackShort", - "AnodeBackTime", - "ScintLeftEnergy", - "ScintLeftShort", - "ScintLeftTime", - "ScintRightEnergy", - "ScintRightShort", - "ScintRightTime", - "CathodeEnergy", - "CathodeShort", - "CathodeTime", - "DelayFrontLeftEnergy", - "DelayFrontLeftShort", - "DelayFrontLeftTime", - "DelayFrontRightEnergy", - "DelayFrontRightShort", - "DelayFrontRightTime", - "DelayBackLeftEnergy", - "DelayBackLeftShort", - "DelayBackLeftTime", - "DelayBackRightEnergy", - "DelayBackRightShort", - "DelayBackRightTime", - "X1", - "X2", - "Xavg", - "Theta", - ]; - - let extra_sps_columns = vec![ - "DelayFrontAverageEnergy", - "DelayBackAverageEnergy", - "DelayFrontLeftTime_AnodeFrontTime", - "DelayFrontRightTime_AnodeFrontTime", - "DelayBackLeftTime_AnodeFrontTime", - "DelayBackRightTime_AnodeFrontTime", - "DelayFrontLeftTime_AnodeBackTime", - "DelayFrontRightTime_AnodeBackTime", - "DelayBackLeftTime_AnodeBackTime", - "DelayBackRightTime_AnodeBackTime", - "AnodeFrontTime_AnodeBackTime", - "AnodeBackTime_AnodeFrontTime", - "AnodeFrontTime_ScintLeftTime", - "AnodeBackTime_ScintLeftTime", - "DelayFrontLeftTime_ScintLeftTime", - "DelayFrontRightTime_ScintLeftTime", - "DelayBackLeftTime_ScintLeftTime", - "DelayBackRightTime_ScintLeftTime", - "ScintRightTime_ScintLeftTime", - ]; - - let mut columns = main_sps_columns - .iter() - .map(|&s| s.to_string()) - .collect::>(); - columns.extend(extra_sps_columns.iter().map(|&s| s.to_string())); - - columns - } - - pub fn main_lfs_names(&self) -> Vec { - let lfs: Vec = ["Raw", "BothPlanes", "OnlyX1Plane", "OnlyX2Plane", "PID"] - .iter() - .map(|&s| s.to_string()) - .collect(); - - lfs - } - - pub fn get_lf(&self, key: &str) -> Option<&LazyFrame> { - self.lfs.get(key) - } - - pub fn add_lf(&mut self, key: &str, lf: LazyFrame) -> &Self { - self.lfs.insert(key.to_string(), lf); - self - } - - pub fn get_column_names_from_lazyframe(lazyframe: &LazyFrame) -> Vec { - let lf: LazyFrame = lazyframe.clone().limit(1); - let df: DataFrame = lf.collect().unwrap(); - let columns: Vec = df - .get_column_names_owned() - .into_iter() - .map(|name| name.to_string()) - .collect(); - - columns - } -} diff --git a/src/histogram_scripter/histogram_script.rs b/src/histogram_scripter/histogram_script.rs index 5c33deb..d911387 100644 --- a/src/histogram_scripter/histogram_script.rs +++ b/src/histogram_scripter/histogram_script.rs @@ -1,16 +1,16 @@ // use super::configure_auxillary_detectors::AuxillaryDetectors; -use super::configure_lazyframes::{LazyFrameInfo, LazyFrames}; use super::manual_histogram_scripts::sps_histograms; +use crate::cutter::cuts::Cut; use crate::histoer::histogrammer::{Histo1DConfig, Histo2DConfig, Histogrammer}; use egui_extras::{Column, TableBuilder}; use polars::prelude::*; #[derive(Clone, Default, serde::Deserialize, serde::Serialize)] pub struct HistogramScript { - pub lazyframe_info: LazyFrameInfo, pub hist_configs: Vec, // Unified vector for both 1D and 2D configurations pub new_columns: Vec<(String, String)>, + pub cuts: Vec, } // Enum to encapsulate 1D and 2D histogram configurations @@ -23,25 +23,12 @@ pub enum HistoConfig { impl HistogramScript { pub fn new() -> Self { Self { - lazyframe_info: LazyFrameInfo::default(), hist_configs: vec![], new_columns: vec![], + cuts: vec![], } } - pub fn get_lazyframe_info(&mut self) { - let mut lazyframe_info = LazyFrameInfo::default(); - - let lazyframes = LazyFrames::new(); - let main_columns = lazyframes.main_column_names(); - let main_lf_names = lazyframes.main_lfs_names(); - - lazyframe_info.lfs = main_lf_names; - lazyframe_info.columns = main_columns; - - self.lazyframe_info = lazyframe_info; - } - pub fn ui(&mut self, ui: &mut egui::Ui) { ui.label("Custom Histogram Scripts"); ui.horizontal(|ui| { @@ -62,6 +49,7 @@ impl HistogramScript { column_name: "".to_string(), range: (0.0, 4096.0), bins: 512, + cuts: vec![], calculate: true, })); } @@ -74,6 +62,7 @@ impl HistogramScript { x_range: (0.0, 4096.0), y_range: (0.0, 4096.0), bins: (512, 512), + cuts: vec![], calculate: true, })); } @@ -88,63 +77,146 @@ impl HistogramScript { ui.separator(); egui::ScrollArea::vertical().show(ui, |ui| { - let mut indices_to_remove_column = Vec::new(); - - ui.heading("Column Creation"); - - TableBuilder::new(ui) - .id_salt("new_columns") - .column(Column::auto()) // expression - .column(Column::auto()) // alias - .column(Column::auto()) // Actions - .striped(true) - .vscroll(false) - .header(20.0, |mut header| { - header.col(|ui| { - ui.label("Expression"); - }); - header.col(|ui| { - ui.label("Alias"); - }); - header.col(|ui| { - if ui.button("Add Column").clicked() { - self.new_columns.push(("".to_string(), "".to_string())); + ui.horizontal(|ui| { + ui.heading("Cuts"); + + if ui.button("+").clicked() { + let mut new_cut = Cut::default(); + if let Err(e) = new_cut.load_cut_from_json() { + log::error!("Failed to load cut: {:?}", e); + } else { + self.cuts.push(new_cut); + } + } + }); + + if self.cuts.is_empty() { + ui.label("No cuts loaded"); + } else { + // Table for Cuts with similar layout to Column Creation and Histograms + let mut indices_to_remove_cut = Vec::new(); + + TableBuilder::new(ui) + .id_salt("cuts_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, cut) in self.cuts.iter_mut().enumerate() { + body.row(18.0, |mut row| { + row.col(|ui| { + ui.add( + egui::TextEdit::singleline(&mut cut.polygon.name) + .hint_text("Cut Name") + .clip_text(false), + ); + }); + row.col(|ui| { + ui.add( + egui::TextEdit::singleline(&mut cut.x_column) + .hint_text("X Column") + .clip_text(false), + ); + }); + row.col(|ui| { + ui.add( + egui::TextEdit::singleline(&mut cut.y_column) + .hint_text("Y Column") + .clip_text(false), + ); + }); + row.col(|ui| { + if ui.button("X").clicked() { + indices_to_remove_cut.push(index); + } + }); + }); } }); - }) - .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(expression) - .hint_text("Expression") - .clip_text(false), - ); - }); - row.col(|ui| { - ui.add( - egui::TextEdit::singleline(alias) - .hint_text("Alias") - .clip_text(false), - ); - }); + // Remove indices in reverse order to prevent shifting issues + for &index in indices_to_remove_cut.iter().rev() { + self.cuts.remove(index); + } + } - row.col(|ui| { - ui.horizontal(|ui| { - if ui.button("X").clicked() { - indices_to_remove_column.push(index); - } + ui.separator(); + + ui.horizontal(|ui| { + ui.heading("Column Creation"); + + if ui.button("+").clicked() { + self.new_columns.push(("".to_string(), "".to_string())); + } + }); + + 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("Expression"); + }); + header.col(|ui| { + ui.label("Alias"); + }); + }) + .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(expression) + .hint_text("Expression") + .clip_text(false), + ); + }); + + row.col(|ui| { + ui.add( + egui::TextEdit::singleline(alias) + .hint_text("Alias") + .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); + // Remove indices in reverse order to prevent shifting issues + for &index in indices_to_remove_column.iter().rev() { + self.new_columns.remove(index); + } } ui.separator(); @@ -161,7 +233,8 @@ impl HistogramScript { .column(Column::auto()) // Columns .column(Column::auto()) // Ranges .column(Column::auto()) // Bins - .column(Column::auto()) // Actions + .column(Column::auto()) // cuts + .column(Column::remainder()) // Actions .striped(true) .vscroll(false) .header(20.0, |mut header| { @@ -180,6 +253,9 @@ impl HistogramScript { header.col(|ui| { ui.label("Bins"); }); + header.col(|ui| { + ui.label("Cuts"); + }); header.col(|ui| { ui.label("Actions"); }); @@ -198,8 +274,7 @@ impl HistogramScript { row.col(|ui| match config { HistoConfig::Histo1D(hist) => { - ui.add_sized( - ui.available_size(), + ui.add( egui::TextEdit::singleline(&mut hist.name) .hint_text("Name") .clip_text(false), @@ -207,8 +282,7 @@ impl HistogramScript { } HistoConfig::Histo2D(hist) => { - ui.add_sized( - ui.available_size(), + ui.add( egui::TextEdit::singleline(&mut hist.name) .hint_text("Name") .clip_text(false), @@ -218,8 +292,7 @@ impl HistogramScript { row.col(|ui| match config { HistoConfig::Histo1D(hist) => { - ui.add_sized( - ui.available_size(), + ui.add( egui::TextEdit::singleline(&mut hist.column_name) .hint_text("Column Name") .clip_text(false), @@ -227,14 +300,12 @@ impl HistogramScript { } HistoConfig::Histo2D(hist) => { ui.vertical(|ui| { - ui.add_sized( - ui.available_size(), + ui.add( egui::TextEdit::singleline(&mut hist.x_column_name) .hint_text("X Column Name") .clip_text(false), ); - ui.add_sized( - ui.available_size(), + ui.add( egui::TextEdit::singleline(&mut hist.y_column_name) .hint_text("Y Column Name") .clip_text(false), @@ -306,6 +377,63 @@ impl HistogramScript { } }); + 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| { + for cut in &self.cuts { + let mut is_selected = hist + .cuts + .iter() + .any(|selected_cut| selected_cut == cut); + if ui + .checkbox(&mut is_selected, &cut.polygon.name) + .clicked() + { + if is_selected && !hist.cuts.contains(cut) { + hist.cuts.push(cut.clone()); + } else if !is_selected { + hist.cuts + .retain(|selected_cut| selected_cut != cut); + } + } + } + }); + } + 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| { + for cut in &self.cuts { + let mut is_selected = hist + .cuts + .iter() + .any(|selected_cut| selected_cut == cut); + if ui + .checkbox(&mut is_selected, &cut.polygon.name) + .clicked() + { + if is_selected && !hist.cuts.contains(cut) { + hist.cuts.push(cut.clone()); + } else if !is_selected { + hist.cuts + .retain(|selected_cut| selected_cut != cut); + } + } + } + }); + } + }); + row.col(|ui| { ui.horizontal(|ui| { match config { diff --git a/src/histogram_scripter/mod.rs b/src/histogram_scripter/mod.rs index a7ad9b1..4fe5bd7 100644 --- a/src/histogram_scripter/mod.rs +++ b/src/histogram_scripter/mod.rs @@ -1,4 +1,2 @@ -// pub mod configure_auxillary_detectors; -pub mod configure_lazyframes; pub mod histogram_script; pub mod manual_histogram_scripts; diff --git a/src/util/processer.rs b/src/util/processer.rs index bf5c50c..bf5701b 100644 --- a/src/util/processer.rs +++ b/src/util/processer.rs @@ -273,69 +273,69 @@ def get_2d_histograms(file_name): } } - pub fn saving_ui(&mut self, ui: &mut egui::Ui) { - ui.collapsing("Parquet Writer", |ui| { - ui.checkbox(&mut self.save_with_scanning, "Save with Scanning") - .on_hover_text( - "This can save files that are larger than memory at the cost of being slower.", - ); - - egui::Grid::new("parquet_writer_grid") - .num_columns(4) - .striped(true) - .show(ui, |ui| { - ui.label(""); - ui.label("Single File"); - ui.label("Individually"); - ui.label("Suffix "); - ui.end_row(); - - ui.label("Non-Filtered"); - - if ui - .add_enabled( - self.workspacer.selected_files.len() > 1, - egui::Button::new("Save"), - ) - .clicked() - { - self.save_selected_files_to_single_file(); - } - - ui.end_row(); - - ui.label("Cut Filtered"); - - if ui - .add_enabled( - self.cut_handler.cuts_are_selected() - && !self.workspacer.selected_files.is_empty(), - egui::Button::new("Save"), - ) - .on_disabled_hover_text("No cuts selected.") - .clicked() - { - self.save_filtered_files_to_single_file(); - } - - if ui - .add_enabled( - self.cut_handler.cuts_are_selected() - && !self.workspacer.selected_files.is_empty(), - egui::Button::new("Save"), - ) - .on_disabled_hover_text("No cuts selected.") - .clicked() - { - self.save_filtered_files_individually(&self.suffix.clone()); - } - - ui.text_edit_singleline(&mut self.suffix); - - ui.end_row(); - }); - }); - } + // pub fn saving_ui(&mut self, ui: &mut egui::Ui) { + // ui.collapsing("Parquet Writer", |ui| { + // ui.checkbox(&mut self.save_with_scanning, "Save with Scanning") + // .on_hover_text( + // "This can save files that are larger than memory at the cost of being slower.", + // ); + + // egui::Grid::new("parquet_writer_grid") + // .num_columns(4) + // .striped(true) + // .show(ui, |ui| { + // ui.label(""); + // ui.label("Single File"); + // ui.label("Individually"); + // ui.label("Suffix "); + // ui.end_row(); + + // ui.label("Non-Filtered"); + + // if ui + // .add_enabled( + // self.workspacer.selected_files.len() > 1, + // egui::Button::new("Save"), + // ) + // .clicked() + // { + // self.save_selected_files_to_single_file(); + // } + + // ui.end_row(); + + // ui.label("Cut Filtered"); + + // if ui + // .add_enabled( + // self.cut_handler.cuts_are_selected() + // && !self.workspacer.selected_files.is_empty(), + // egui::Button::new("Save"), + // ) + // .on_disabled_hover_text("No cuts selected.") + // .clicked() + // { + // self.save_filtered_files_to_single_file(); + // } + + // if ui + // .add_enabled( + // self.cut_handler.cuts_are_selected() + // && !self.workspacer.selected_files.is_empty(), + // egui::Button::new("Save"), + // ) + // .on_disabled_hover_text("No cuts selected.") + // .clicked() + // { + // self.save_filtered_files_individually(&self.suffix.clone()); + // } + + // ui.text_edit_singleline(&mut self.suffix); + + // ui.end_row(); + // }); + // }); + // } pub fn ui(&mut self, ui: &mut egui::Ui) { if !self.workspacer.options.root { @@ -351,17 +351,17 @@ def get_2d_histograms(file_name): self.calculate_histograms(); } - if ui - .add_enabled( - !self.workspacer.selected_files.is_empty() - && self.cut_handler.cuts_are_selected(), - egui::Button::new("with Cuts"), - ) - .on_disabled_hover_text("No files selected or cuts selected.") - .clicked() - { - self.calculate_histograms_with_cuts(); - } + // if ui + // .add_enabled( + // !self.workspacer.selected_files.is_empty() + // && self.cut_handler.cuts_are_selected(), + // egui::Button::new("with Cuts"), + // ) + // .on_disabled_hover_text("No files selected or cuts selected.") + // .clicked() + // { + // self.calculate_histograms_with_cuts(); + // } if self.histogrammer.calculating.load(Ordering::Relaxed) { // Show spinner while `calculating` is true @@ -390,9 +390,9 @@ def get_2d_histograms(file_name): ui.separator(); - self.saving_ui(ui); + // self.saving_ui(ui); - ui.separator(); + // ui.separator(); if let Some(lazyframer) = &mut self.lazyframer { lazyframer.ui(ui);