1use std::collections::{
7 HashMap,
8 VecDeque,
9};
10use std::sync::{
11 Arc,
12 Mutex,
13};
14
15use crossbeam_channel::{
16 Receiver,
17 };
19
20use ratatui::prelude::*;
21use ratatui::symbols::Marker;
22
23use ratatui::Frame;
24use ratatui::layout::Rect;
25use ratatui::widgets::{
26 Block,
27 BorderType,
28 Borders,
29 Paragraph,
30 List,
31 ListItem,
32 ListState,
33 canvas::{
34 Canvas,
35 Points},
38};
39
40use ndhistogram::{
41 ndhistogram,
42 Histogram,
43 Hist1D,
44};
45use ndhistogram::axis::{
46 Uniform,
47};
48
49use tof_dataclasses::errors::SerializationError;
51use tof_dataclasses::packets::TofPacket;
52use tof_dataclasses::events::{
53 TofEventSummary,
56 RBWaveform,
60};
61use tof_dataclasses::calibrations::RBCalibrations;
62use tof_dataclasses::database::Paddle;
63
64use crate::colors::ColorTheme;
65use crate::menu::{
66 PaddleMenu,
67 UIMenu,
68 UIMenuItem
69};
70
71use crate::widgets::{
72 prep_data,
73 create_labels,
74 histogram,
75 timeseries,
76};
77
78#[derive(Debug, Clone)]
79pub struct PaddleTab<'a> {
80 pub theme : ColorTheme,
81 pub te_receiver : Receiver<TofEventSummary>,
82 pub event_queue : VecDeque<TofEventSummary>,
83 pub wf_receiver : Receiver<TofPacket>,
84 pub queue_size : usize,
85 pub menu : PaddleMenu<'a>,
86 pub wf : HashMap<u8, RBWaveform>,
87 pub last_wf_ch_a : HashMap<u8, VecDeque<(f64, f64)>>,
88 pub last_wf_ch_b : HashMap<u8, VecDeque<(f64, f64)>>,
89 pub wf_label_a : String,
90 pub wf_label_b : String,
91 pub calibrations : HashMap<u8, RBCalibrations>,
93 pub baseline_ch_a : HashMap<u8, Hist1D<Uniform<f32>>>,
94 pub baseline_ch_b : HashMap<u8, Hist1D<Uniform<f32>>>,
95 pub baseline_rms_ch_a : HashMap<u8, Hist1D<Uniform<f32>>>,
96 pub baseline_rms_ch_b : HashMap<u8, Hist1D<Uniform<f32>>>,
97
98 pub h_edep : HashMap<u8, Hist1D<Uniform<f32>>>,
100 pub h_rel_pos : HashMap<u8, Hist1D<Uniform<f32>>>,
101
102 pub pca_histo : HashMap<u8, Hist1D<Uniform<f32>>>,
103 pub pcb_histo : HashMap<u8, Hist1D<Uniform<f32>>>,
104 pub pha_histo : HashMap<u8, Hist1D<Uniform<f32>>>,
105 pub phb_histo : HashMap<u8, Hist1D<Uniform<f32>>>,
106 pub pta_histo : HashMap<u8, Hist1D<Uniform<f32>>>,
107 pub ptb_histo : HashMap<u8, Hist1D<Uniform<f32>>>,
108
109 pub charge_a : HashMap<u8, VecDeque<f64>>,
111 pub charge_b : HashMap<u8, VecDeque<f64>>,
112
113 pub all_paddles : HashMap<u8, Paddle>,
115 pub pdl_state : ListState,
116 pub current_paddle : Paddle,
117 pub pdl_items : Vec::<ListItem<'a>>,
118 pub pdl_active : bool,
119 pub pdl_selector : usize,
120 pub pdl_changed : bool,
121}
122
123impl PaddleTab<'_> {
124 pub fn new(te_receiver : Receiver<TofEventSummary>,
125 wf_receiver : Receiver<TofPacket>,
126 all_paddles : HashMap<u8, Paddle>,
127 calibrations: Arc<Mutex<HashMap<u8, RBCalibrations>>>,
128 theme : ColorTheme) -> Self {
129 let theme_c = theme.clone();
130 let mut pd_select_items = Vec::<ListItem>::new();
131 for k in 1..161 {
132 let this_item = format!(" Paddle{:0>3}", k);
133 pd_select_items.push(ListItem::new(Line::from(this_item)));
134 }
135 let mut calibrations_cloned = HashMap::<u8, RBCalibrations>::new();
137 match calibrations.lock() {
138 Err(_err) => error!("Unable to get lock on rbcalibrations!"),
139 Ok(cali) => {
140 calibrations_cloned = cali.clone();
141 }
142 }
143 let mut charge_a = HashMap::<u8, VecDeque<f64>>::new();
144 let mut charge_b = HashMap::<u8, VecDeque<f64>>::new();
145 let mut wf = HashMap::<u8, RBWaveform>::new();
146 let mut bl_ch_a = HashMap::<u8, Hist1D<Uniform<f32>>>::new();
147 let mut bl_ch_b = HashMap::<u8, Hist1D<Uniform<f32>>>::new();
148 let mut blrms_ch_a = HashMap::<u8, Hist1D<Uniform<f32>>>::new();
149 let mut blrms_ch_b = HashMap::<u8, Hist1D<Uniform<f32>>>::new();
150 let mut h_edep_ = HashMap::<u8, Hist1D<Uniform<f32>>>::new();
151 let mut h_rel_pos_ = HashMap::<u8, Hist1D<Uniform<f32>>>::new();
152 let mut pca_histo = HashMap::<u8, Hist1D<Uniform<f32>>>::new();
153 let mut pcb_histo = HashMap::<u8, Hist1D<Uniform<f32>>>::new();
154 let mut pha_histo = HashMap::<u8, Hist1D<Uniform<f32>>>::new();
155 let mut phb_histo = HashMap::<u8, Hist1D<Uniform<f32>>>::new();
156 let mut pta_histo = HashMap::<u8, Hist1D<Uniform<f32>>>::new();
157 let mut ptb_histo = HashMap::<u8, Hist1D<Uniform<f32>>>::new();
158 let bins_bl = Uniform::new(20, -2.0, 2.0).unwrap();
159 let bins_bl_rms = Uniform::new(20, 0.0, 2.0).unwrap();
160 let bins_edep = Uniform::new(50, 0.0, 25.0).unwrap();
161 let bins_relpos = Uniform::new(50, 0.0, 1.2).unwrap();
162 let bins_ph = Uniform::new(50, 0.0, 200.0).unwrap();
163 let bins_pt = Uniform::new(50, 25.0, 350.0).unwrap();
164 let bins_pc = Uniform::new(30, 0.0, 40.0).unwrap();
165 let mut lwf_ch_a = HashMap::<u8, VecDeque<(f64, f64)>>::new();
166 let mut lwf_ch_b = HashMap::<u8, VecDeque<(f64, f64)>>::new();
167 for pid in 1..161 {
168 charge_a.insert(pid, VecDeque::<f64>::new());
169 charge_b.insert(pid, VecDeque::<f64>::new());
170 wf.insert(pid, RBWaveform::new());
172 bl_ch_a.insert(pid, ndhistogram!(bins_bl.clone()));
173 bl_ch_b.insert(pid, ndhistogram!(bins_bl.clone()));
174 blrms_ch_a.insert(pid, ndhistogram!(bins_bl_rms.clone()));
175 blrms_ch_b.insert(pid, ndhistogram!(bins_bl_rms.clone()));
176 h_edep_.insert(pid, ndhistogram!(bins_edep.clone()));
177 h_rel_pos_.insert(pid, ndhistogram!(bins_relpos.clone()));
178 pca_histo.insert(pid, ndhistogram!(bins_pc .clone()));
179 pcb_histo.insert(pid, ndhistogram!(bins_pc .clone()));
180 pha_histo.insert(pid, ndhistogram!(bins_ph .clone()));
181 phb_histo.insert(pid, ndhistogram!(bins_ph .clone()));
182 pta_histo.insert(pid, ndhistogram!(bins_pt .clone()));
183 ptb_histo.insert(pid, ndhistogram!(bins_pt .clone()));
184 lwf_ch_a.insert(pid, VecDeque::<(f64,f64)>::new());
185 lwf_ch_b.insert(pid, VecDeque::<(f64,f64)>::new());
186 }
187
188 Self {
189 theme,
190 te_receiver,
191 wf_receiver,
192 event_queue : VecDeque::<TofEventSummary>::new(),
193 queue_size : 10000, menu : PaddleMenu::new(theme_c),
196 wf : wf,
197 wf_label_a : String::from("A"),
198 wf_label_b : String::from("B"),
199 last_wf_ch_a : lwf_ch_a,
200 last_wf_ch_b : lwf_ch_b,
201 calibrations : calibrations_cloned,
202 baseline_ch_a : bl_ch_a,
203 baseline_ch_b : bl_ch_b,
204 baseline_rms_ch_a : blrms_ch_a,
205 baseline_rms_ch_b : blrms_ch_b,
206 h_edep : h_edep_,
207 h_rel_pos : h_rel_pos_,
208 pca_histo,
209 pcb_histo,
210 pha_histo,
211 phb_histo,
212 pta_histo,
213 ptb_histo,
214 charge_a ,
215 charge_b ,
216 all_paddles,
217 pdl_items : pd_select_items,
218 pdl_state : ListState::default(),
219 current_paddle : Paddle::new(),
220 pdl_active : false,
221 pdl_selector : 1,
222 pdl_changed : false,
223 }
224 }
225
226 pub fn next_pd(&mut self) {
227 let i = match self.pdl_state.selected() {
228 Some(i) => {
229 if i >= self.pdl_items.len() - 1 {
230 self.pdl_items.len() - 1
231 } else {
232 i + 1
233 }
234 }
235 None => 0,
236 };
237 self.pdl_state.select(Some(i));
238 }
239
240 pub fn prev_pd(&mut self) {
241 let i = match self.pdl_state.selected() {
242 Some(i) => {
243 if i == 0 {
244 0
245 } else {
246 i - 1
247 }
248 }
249 None => 0,
250 };
251 self.pdl_state.select(Some(i));
252 }
253
254 pub fn unselect_pdl(&mut self) {
255 self.pdl_state.select(None);
256 }
257
258 pub fn receive_packet(&mut self) -> Result<(), SerializationError> {
259 match self.wf_receiver.try_recv() {
260 Err(_err) => {
261 }
262 Ok(wf_pack) => {
263 let mut wf : RBWaveform = wf_pack.unpack()?;
264 match self.calibrations.get(&wf.rb_id) {
265 None => error!("RBCalibrations for board {} not available!", wf.rb_id),
266 Some(rbcal) => {
267 match wf.calibrate(rbcal) {
268 Err(err) => error!("Calibration error! {err}"),
269 Ok(_) => ()
270 }
271 }
272 }
273 if wf.paddle_id == self.current_paddle.paddle_id as u8 {
274 let rb_channel_a = wf.rb_channel_a + 1;
275 let rb_channel_b = wf.rb_channel_b + 1;
276 if (rb_channel_a != self.current_paddle.rb_chA as u8 )
277 || (rb_channel_b != self.current_paddle.rb_chB as u8 ) {
278 error!("Inconsistent paddle RB channels! Maybe A and B are switched!");
279 }
280 }
281 if wf.paddle_id == 0 {
282 error!("Got waveform with padle id 0!");
283 } else if wf.paddle_id > 160 {
284 error!("Got paddle id which is too large! {}", wf.paddle_id);
285 } else {
286 let pid = wf.paddle_id as u8;
287 *self.wf.get_mut(&pid).unwrap() = wf;
288 }
289 }
290 }
291 match self.te_receiver.try_recv() {
292 Err(_err) => {
293 return Ok(());
294 },
295 Ok(mut ev) => {
296 for h in &mut ev.hits {
299 self.h_edep.get_mut(&(h.paddle_id as u8)).unwrap().fill(&h.get_edep());
300 h.set_paddle(&self.current_paddle);
301 let rel_pos = h.get_pos()/(self.current_paddle.length*10.0);
302 self.h_rel_pos.get_mut(&h.paddle_id).unwrap().fill(&rel_pos);
303 self.pha_histo.get_mut(&h.paddle_id).unwrap().fill(&h.get_peak_a());
304 self.phb_histo.get_mut(&h.paddle_id).unwrap().fill(&h.get_peak_b());
305 self.pca_histo.get_mut(&h.paddle_id).unwrap().fill(&h.get_charge_a());
306 self.pcb_histo.get_mut(&h.paddle_id).unwrap().fill(&h.get_charge_b());
307 self.pta_histo.get_mut(&h.paddle_id).unwrap().fill(&h.get_time_a());
308 self.ptb_histo.get_mut(&h.paddle_id).unwrap().fill(&h.get_time_a());
309
310 self.charge_a.get_mut(&(h.paddle_id as u8)).unwrap().push_back(h.get_charge_a() as f64);
311 self.charge_b.get_mut(&(h.paddle_id as u8)).unwrap().push_back(h.get_charge_b() as f64);
312 if self.charge_a.get_mut(&(h.paddle_id as u8)).unwrap().len() > self.queue_size {
313 self.charge_a.get_mut(&(h.paddle_id as u8)).unwrap().pop_front();
314 }
315 if self.charge_b.get_mut(&(h.paddle_id as u8)).unwrap().len() > self.queue_size {
316 self.charge_b.get_mut(&(h.paddle_id as u8)).unwrap().pop_front();
317 }
318 let ch_a_bl = h.get_bl_a();
319 let ch_b_bl = h.get_bl_b();
320 if -2.0 < ch_a_bl && ch_b_bl < 2.0 {
324 self.baseline_ch_a.get_mut(&(h.paddle_id as u8)).unwrap().fill(&ch_a_bl);
325 }
326 if -2.0 < ch_b_bl && ch_b_bl < 2.0 {
327 self.baseline_ch_b.get_mut(&(h.paddle_id as u8)).unwrap().fill(&ch_b_bl);
328 }
329 self.baseline_rms_ch_a.get_mut(&(h.paddle_id as u8)).unwrap().fill(&h.get_bl_a_rms());
331 self.baseline_rms_ch_b.get_mut(&(h.paddle_id as u8)).unwrap().fill(&h.get_bl_b_rms());
333 }
334 return Ok(());
335 }
336 }
337 }
338
339 pub fn render(&mut self, main_window : &Rect, frame : &mut Frame) {
341
342 match self.menu.get_active_menu_item() {
343 UIMenuItem::Back => {
344 let main_lo = Layout::default()
346 .direction(Direction::Horizontal)
347 .constraints(
348 [Constraint::Percentage(15), Constraint::Percentage(85)].as_ref(),
349 )
350 .split(*main_window);
351 let pdl = Block::default()
352 .borders(Borders::ALL)
353 .style(self.theme.style())
354 .title("Select Paddle")
355 .border_type(BorderType::Plain);
356 let pd_select_list = List::new(self.pdl_items.clone()).block(pdl)
357 .highlight_style(self.theme.highlight().add_modifier(Modifier::BOLD))
358 .highlight_symbol(">>")
359 .repeat_highlight_symbol(true);
360 match self.pdl_state.selected() {
361 None => {
362 let selector = 1;
363 if self.pdl_selector != selector {
364 self.pdl_changed = true;
365 self.pdl_selector = selector;
366 } else {
367 self.pdl_changed = false;
368 }
369 },
370 Some(_pid) => {
371 let selector = _pid + 1;
372 if self.pdl_selector != selector {
373 self.pdl_changed = true;
374 self.pdl_selector = selector;
375 } else {
376 self.pdl_changed = false;
377 }
378 }
379 }
380 let view_string : String;
381 match self.all_paddles.get(&(self.pdl_selector as u8)) {
382 Some(_pd) => {
383 view_string = format!("{}", _pd);
384 self.current_paddle = _pd.clone();
385 }
386 None => {
387 view_string = format!("No information for Paddle {} in DB or DB not available!", self.pdl_selector);
388 }
389 }
390 let pd_view = Paragraph::new(view_string)
391 .style(self.theme.style())
392 .alignment(Alignment::Left)
393 .block(
395 Block::default()
396 .borders(Borders::ALL)
397 .style(self.theme.style())
398 .title("Paddle")
399 .border_type(BorderType::Rounded),
400 );
401 frame.render_stateful_widget(pd_select_list, main_lo[0], &mut self.pdl_state );
402 frame.render_widget(pd_view, main_lo[1]);
403 }
404 UIMenuItem::Signal => {
405 let main_lo = Layout::default()
406 .direction(Direction::Horizontal)
407 .constraints(
408 [Constraint::Percentage(50),
409 Constraint::Percentage(50)].as_ref(),
410 )
411 .split(*main_window);
412 let wf_lo = Layout::default()
413 .direction(Direction::Vertical)
414 .constraints(
415 [Constraint::Percentage(40),
416 Constraint::Percentage(40),
417 Constraint::Percentage(20)].as_ref(),
418 )
419 .split(main_lo[0]);
420 let ch_lo = Layout::default()
421 .direction(Direction::Vertical)
422 .constraints(
423 [Constraint::Percentage(80),
424 Constraint::Percentage(20)].as_ref(),
425 )
426 .split(main_lo[1]);
427 let bla_lo = Layout::default()
428 .direction(Direction::Horizontal)
429 .constraints(
430 [Constraint::Percentage(50),
431 Constraint::Percentage(50)].as_ref(),
432 )
433 .split(wf_lo[2]);
434 let blb_lo = Layout::default()
435 .direction(Direction::Horizontal)
436 .constraints(
437 [Constraint::Percentage(50),
438 Constraint::Percentage(50)].as_ref(),
439 )
440 .split(ch_lo[1]);
441
442 let mut wf_data_a = VecDeque::<(f64, f64)>::new();
443 let mut wf_data_b = VecDeque::<(f64, f64)>::new();
444 let wf_theme = self.theme.clone();
447 match self.wf.get_mut(&(self.current_paddle.paddle_id as u8)) {
448 None => {
449 }
453 Some(wf) => {
454 if wf.voltages_a.len() == 0 {
456 for (i,k) in wf.adc_a.iter().enumerate() {
457 wf_data_a.push_back((i as f64, *k as f64));
458 }
459 } else {
460 for k in 0..wf.nanoseconds_a.len() {
461 wf_data_a.push_back((wf.nanoseconds_a[k] as f64, wf.voltages_a[k] as f64));
462 }
463 }
464 if wf.voltages_b.len() == 0 {
467 for (i,k) in wf.adc_b.iter().enumerate() {
468 wf_data_b.push_back((i as f64, *k as f64));
469 }
470 } else {
471 for k in 0..wf.nanoseconds_b.len() {
472 wf_data_b.push_back((wf.nanoseconds_b[k] as f64, wf.voltages_b[k] as f64));
473 }
474 }
475 }
477 }
478
479 let wf_chart_a = timeseries(&mut wf_data_a,
480 self.wf_label_a.clone(),
481 self.wf_label_a.clone(),
482 &wf_theme);
483 let wf_chart_b = timeseries(&mut wf_data_b,
484 self.wf_label_b.clone(),
485 self.wf_label_b.clone(),
486 &wf_theme);
487 frame.render_widget(wf_chart_a, wf_lo[0]);
488 frame.render_widget(wf_chart_b, wf_lo[1]);
489
490 let mut ch2d_points = Vec::<(f64, f64)>::new();
492 for k in 0..self.charge_a.get(&(self.current_paddle.paddle_id as u8)).unwrap().len() {
493 ch2d_points.push((self.charge_a.get(&(self.current_paddle.paddle_id as u8)).unwrap()[k],
494 self.charge_b.get(&(self.current_paddle.paddle_id as u8)).unwrap()[k]));
495 }
496
497 let charge_plot = Canvas::default()
498 .block(Block::bordered().title("Charge AvsB"))
499 .marker(Marker::Braille)
500 .paint(|ctx| {
501 let points = Points {
516 coords : &ch2d_points.as_slice(),
517 color : self.theme.hc,
518 };
519 ctx.draw(&points);
520 })
523 .x_bounds([0.0, 200.0])
524 .y_bounds([0.0, 200.0]);
525 frame.render_widget(charge_plot, ch_lo[0]);
526
527 let bl_a_labels = create_labels(&self.baseline_ch_a.get(&(self.current_paddle.paddle_id as u8)).unwrap());
530 let bl_a_data = prep_data(&self.baseline_ch_a.get(&(self.current_paddle.paddle_id as u8)).unwrap(), &bl_a_labels, 1, false);
531 let bl_a_chart = histogram(bl_a_data, String::from("Baseline Side A [mV]"), 2, 0, &self.theme);
532 frame.render_widget(bl_a_chart, bla_lo[0]);
533
534 let bl_a_rms_data = prep_data(&self.baseline_rms_ch_a.get(&(self.current_paddle.paddle_id as u8)).unwrap(), &bl_a_labels, 1, false);
535 let bl_a_rms_chart = histogram(bl_a_rms_data, String::from("Baseline RMS Side A [mV]"), 2, 0, &self.theme);
536 frame.render_widget(bl_a_rms_chart, bla_lo[1]);
537
538 let bl_b_data = prep_data(&self.baseline_ch_b.get(&(self.current_paddle.paddle_id as u8)).unwrap(), &bl_a_labels, 1, false);
541 let bl_b_chart = histogram(bl_b_data, String::from("Baseline Side B [mV]"), 2, 0, &self.theme);
542 frame.render_widget(bl_b_chart, blb_lo[0]);
543
544 let bl_b_rms_data = prep_data(&self.baseline_rms_ch_b.get(&(self.current_paddle.paddle_id as u8)).unwrap(), &bl_a_labels, 1, false);
546 let bl_b_rms_chart = histogram(bl_b_rms_data, String::from("Baseline RMS Side B [mV]"), 2, 0, &self.theme);
547 frame.render_widget(bl_b_rms_chart, blb_lo[1]);
548 }
549 UIMenuItem::RecoVars => {
550 let main_lo = Layout::default()
551 .direction(Direction::Horizontal)
552 .constraints(
553 [Constraint::Percentage(60), Constraint::Percentage(40)].as_ref(),
554 )
555 .split(*main_window);
556 let col_left = Layout::default()
557 .direction(Direction::Horizontal)
558 .constraints(
559 [Constraint::Percentage(50), Constraint::Percentage(50)].as_ref(),
560 )
561 .split(main_lo[0]);
562 let rows_right = Layout::default()
563 .direction(Direction::Vertical)
564 .constraints(
565 [Constraint::Percentage(33),
566 Constraint::Percentage(33),
567 Constraint::Percentage(34)].as_ref(),
568 )
569 .split(main_lo[1]);
570 let rows_left_left = Layout::default()
571 .direction(Direction::Vertical)
572 .constraints(
573 [Constraint::Percentage(33),
574 Constraint::Percentage(33),
575 Constraint::Percentage(34)].as_ref(),
576 )
577 .split(col_left[0]);
578 let rows_left_right = Layout::default()
579 .direction(Direction::Vertical)
580 .constraints(
581 [Constraint::Percentage(33),
582 Constraint::Percentage(33),
583 Constraint::Percentage(34)].as_ref(),
584 )
585 .split(col_left[1]);
586
587 let pid = self.current_paddle.paddle_id as u8;
589
590 let ph_labels = create_labels(&self.pha_histo.get(&pid).unwrap());
591 let pha_data = prep_data(&self.pha_histo.get(&pid).unwrap(), &ph_labels, 5, false);
592 let pha_chart = histogram(pha_data, String::from("Pulse height SideA [mV]"), 2, 0, &self.theme);
593 frame.render_widget(pha_chart, rows_left_left[0]);
594 let phb_data = prep_data(&self.phb_histo.get(&pid).unwrap(), &ph_labels, 5, false);
595 let phb_chart = histogram(phb_data, String::from("Pulse height SideB [mV]"), 2, 0, &self.theme);
596 frame.render_widget(phb_chart, rows_left_right[0]);
597
598 let pt_labels = create_labels(&self.pta_histo.get(&pid).unwrap());
599 let pta_data = prep_data(&self.pta_histo.get(&pid).unwrap(), &pt_labels, 5, false);
600 let pta_chart = histogram(pta_data, String::from("Pulse time SideA [a.u.]"), 2, 0, &self.theme);
601 frame.render_widget(pta_chart, rows_left_left[1]);
602
603 let ptb_data = prep_data(&self.ptb_histo.get(&pid).unwrap(), &pt_labels, 5, false);
604 let ptb_chart = histogram(ptb_data, String::from("Pulse time SideB [a.u.]"), 2, 0, &self.theme);
605 frame.render_widget(ptb_chart, rows_left_right[1]);
606
607 let pc_labels = create_labels(&self.pca_histo.get(&pid).unwrap());
608 let pca_data = prep_data(&self.pca_histo.get(&pid).unwrap(), &pc_labels, 5, false);
609 let pca_chart = histogram(pca_data, String::from("Pulse charge SideA [mC]"), 2, 0, &self.theme);
610 frame.render_widget(pca_chart, rows_left_left[2]);
611
612 let pcb_data = prep_data(&self.pcb_histo.get(&pid).unwrap(), &pc_labels, 5, false);
613 let pcb_chart = histogram(pcb_data, String::from("Pulse charge SideB [mC]"), 2, 0, &self.theme);
614 frame.render_widget(pcb_chart, rows_left_right[2]);
615
616 let edep_labels = create_labels(&self.h_edep.get(&(self.current_paddle.paddle_id as u8)).unwrap());
618 let edep_data = prep_data(&self.h_edep.get (&(self.current_paddle.paddle_id as u8)).unwrap(), &edep_labels, 1, false);
619 let edep_chart = histogram(edep_data, String::from("Reco. Energy Deposition [minI]"), 1, 0, &self.theme);
620 frame.render_widget(edep_chart, rows_right[0]);
621 let relpos_labels = create_labels(&self.h_rel_pos.get(&(self.current_paddle.paddle_id as u8)).unwrap());
623 let relpos_data = prep_data(&self.h_rel_pos.get (&(self.current_paddle.paddle_id as u8)).unwrap(), &relpos_labels, 1, false);
624 let relpos_chart = histogram(relpos_data, String::from("Rel. pos. (1 = B side)"), 1, 0, &self.theme);
625 frame.render_widget(relpos_chart, rows_right[1]);
626 }
627 _ => ()
628 } }
630}