1use crate::prelude::*;
13
14#[derive(Debug, Clone, PartialEq, serde::Deserialize, serde::Serialize)]
16pub enum ParameterSetStrategy {
17 ControlServer,
19 Board
21}
22
23#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
25pub struct MTBSettings {
26 pub trigger_type : TriggerType,
28 pub trigger_prescale : f32,
35 pub use_combo_trigger : bool,
37 pub global_trigger_type : TriggerType,
40 pub global_trigger_prescale : f32,
42
43 pub poisson_trigger_rate : u32,
45 pub gaps_trigger_use_beta : bool,
48 pub trace_suppression : bool,
64 pub mtb_timeout_sec : u64,
68 pub mtb_moni_interval : u64,
71 pub rb_int_window : u8,
72 pub tiu_emulation_mode : bool,
73 pub tiu_ignore_busy : bool,
74 pub tofbot_webhook : String,
75 pub hb_send_interval : u64,
76 pub use_fixed_deadtime : Option<bool>,
81}
82
83impl MTBSettings {
84 pub fn new() -> Self {
85 Self {
86 trigger_type : TriggerType::Unknown,
87 trigger_prescale : 0.0,
88 poisson_trigger_rate : 0,
89 gaps_trigger_use_beta : true,
90 trace_suppression : true,
91 mtb_timeout_sec : 60,
92 mtb_moni_interval : 30,
93 rb_int_window : 1,
94 tiu_emulation_mode : false,
95 tiu_ignore_busy : false,
96 tofbot_webhook : String::from(""),
97 hb_send_interval : 30,
98 use_combo_trigger : false,
99 global_trigger_type : TriggerType::Unknown,
100 global_trigger_prescale : 1.0,
101 use_fixed_deadtime : None,
102 }
103 }
104
105 pub fn emit_triggerconfig(&self) -> TriggerConfig {
108 let mut cfg = TriggerConfig::new();
109 cfg.active_fields = u32::MAX;
113 cfg.gaps_trigger_use_beta = Some(self.gaps_trigger_use_beta);
114 cfg.prescale = Some(self.trigger_prescale);
115 cfg.trigger_type = Some(self.trigger_type);
116 cfg.use_combo_trigger = Some(self.use_combo_trigger);
117 cfg.combo_trigger_type = Some(self.global_trigger_type);
118 cfg.combo_trigger_prescale = Some(self.global_trigger_prescale);
119 cfg.trace_suppression = Some(self.trace_suppression);
120 cfg.mtb_moni_interval = Some((self.mtb_moni_interval & 0xffff) as u16);
121 cfg.tiu_ignore_busy = Some(self.tiu_ignore_busy);
122 cfg.hb_send_interval = Some((self.hb_send_interval & 0xffff) as u16);
123 cfg
124 }
125
126 pub fn from_triggerconfig(&mut self, cfg : &TriggerConfig) {
128 if cfg.gaps_trigger_use_beta.is_some() {
129 self.gaps_trigger_use_beta = cfg.gaps_trigger_use_beta.unwrap() ;
130 }
131 if cfg.prescale.is_some() {
132 self.trigger_prescale = cfg.prescale.unwrap() ;
133 }
134 if cfg.trigger_type.is_some() {
135 self.trigger_type = cfg.trigger_type.unwrap() ;
136 }
137 if cfg.use_combo_trigger.is_some() {
138 self.use_combo_trigger = cfg.use_combo_trigger.unwrap() ;
139 }
140 if cfg.combo_trigger_type.is_some() {
141 self.global_trigger_type = cfg.combo_trigger_type.unwrap() ;
142 }
143 if cfg.combo_trigger_prescale.is_some() {
144 self.global_trigger_prescale = cfg.combo_trigger_prescale.unwrap();
145 }
146 if cfg.trace_suppression.is_some() {
147 self.trace_suppression = cfg.trace_suppression.unwrap() ;
148 }
149 if cfg.mtb_moni_interval.is_some() {
150 self.mtb_moni_interval = cfg.mtb_moni_interval.unwrap() as u64;
151 }
152 if cfg.tiu_ignore_busy.is_some() {
153 self.tiu_ignore_busy = cfg.tiu_ignore_busy.unwrap() ;
154 }
155 if cfg.hb_send_interval.is_some() {
156 self.hb_send_interval = cfg.hb_send_interval.unwrap() as u64;
157 }
158 }
159}
160
161impl fmt::Display for MTBSettings {
162 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
163 let disp = toml::to_string(self).unwrap_or(
164 String::from("-- DESERIALIZATION ERROR! --"));
165 write!(f, "<MTBSettings :\n{}>", disp)
166 }
167}
168
169impl Default for MTBSettings {
170 fn default() -> Self {
171 Self::new()
172 }
173}
174
175#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
176pub struct PreampSettings {
177 pub set_preamp_voltages : bool,
179 pub set_strategy : ParameterSetStrategy,
182 pub rat_preamp_biases : HashMap<String, [f32;16]>
184}
185
186impl PreampSettings {
187 pub fn new() -> Self {
188 let default_biases = HashMap::from([
190 (String::from("RAT01"), [58.0;16]),
191 (String::from("RAT02"), [58.0;16]),
192 (String::from("RAT03"), [58.0;16]),
193 (String::from("RAT04"), [58.0;16]),
194 (String::from("RAT05"), [58.0;16]),
195 (String::from("RAT06"), [58.0;16]),
196 (String::from("RAT07"), [58.0;16]),
197 (String::from("RAT08"), [58.0;16]),
198 (String::from("RAT09"), [58.0;16]),
199 (String::from("RAT10"), [58.0;16]),
200 (String::from("RAT11"), [58.0;16]),
201 (String::from("RAT12"), [58.0;16]),
202 (String::from("RAT13"), [58.0;16]),
203 (String::from("RAT14"), [58.0;16]),
204 (String::from("RAT15"), [58.0;16]),
205 (String::from("RAT16"), [58.0;16]),
206 (String::from("RAT17"), [58.0;16]),
207 (String::from("RAT18"), [58.0;16]),
208 (String::from("RAT19"), [58.0;16]),
209 (String::from("RAT20"), [58.0;16])]);
210
211 Self {
212 set_preamp_voltages : false,
213 set_strategy : ParameterSetStrategy::ControlServer,
214 rat_preamp_biases : default_biases,
215 }
216 }
217
218 #[cfg(feature="database")]
219 pub fn emit_pb_settings_packets(&self, rats : &HashMap<u8,RAT>) -> Vec<TofPacket> {
220 let mut packets = Vec::<TofPacket>::new();
221 for k in rats.keys() {
222 let rat = &rats[&k];
223 let rat_key = format!("RAT{:2}", rat);
224 let mut cmd = TofCommand::new();
225 cmd.command_code = TofCommandCode::SetPreampBias;
226 let mut payload = PreampBiasConfig::new();
227 payload.rb_id = rat.rb2_id as u8;
228 if *k as usize >= self.rat_preamp_biases.len() {
229 error!("RAT ID {k} larger than 20!");
230 continue;
231 }
232 payload.biases = self.rat_preamp_biases[&rat_key];
233 cmd.payload = payload.to_bytestream();
234 let tp = cmd.pack();
235 packets.push(tp);
236 }
237 packets
238 }
239}
240
241impl fmt::Display for PreampSettings {
242 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
243 let disp : String;
244 match toml::to_string(self) {
245 Err(err) => {
246 error!("Deserialization error! {err}");
247 disp = String::from("-- DESERIALIZATION ERROR! --");
248 }
249 Ok(_disp) => {
250 disp = _disp;
251 }
252 }
253 write!(f, "<PreampBiasSettings :\n{}>", disp)
254 }
255}
256
257impl Default for PreampSettings {
258 fn default() -> Self {
259 Self::new()
260 }
261}
262
263#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
264pub struct LTBThresholdSettings {
265 pub set_ltb_thresholds : bool,
267 pub set_strategy : ParameterSetStrategy,
270 pub rat_ltb_thresholds : HashMap<String, [f32;3]>
272}
273
274impl LTBThresholdSettings {
275 pub fn new() -> Self {
276 let default_thresholds = HashMap::from([
277 (String::from("RAT01"), [40.0,32.0,375.0]),
278 (String::from("RAT02"), [40.0,32.0,375.0]),
279 (String::from("RAT03"), [40.0,32.0,375.0]),
280 (String::from("RAT04"), [40.0,32.0,375.0]),
281 (String::from("RAT05"), [40.0,32.0,375.0]),
282 (String::from("RAT06"), [40.0,32.0,375.0]),
283 (String::from("RAT07"), [40.0,32.0,375.0]),
284 (String::from("RAT08"), [40.0,32.0,375.0]),
285 (String::from("RAT09"), [40.0,32.0,375.0]),
286 (String::from("RAT10"), [40.0,32.0,375.0]),
287 (String::from("RAT11"), [40.0,32.0,375.0]),
288 (String::from("RAT12"), [40.0,32.0,375.0]),
289 (String::from("RAT13"), [40.0,32.0,375.0]),
290 (String::from("RAT14"), [40.0,32.0,375.0]),
291 (String::from("RAT15"), [40.0,32.0,375.0]),
292 (String::from("RAT16"), [40.0,32.0,375.0]),
293 (String::from("RAT17"), [40.0,32.0,375.0]),
294 (String::from("RAT18"), [40.0,32.0,375.0]),
295 (String::from("RAT19"), [40.0,32.0,375.0]),
296 (String::from("RAT20"), [40.0,32.0,375.0])]);
297
298 Self {
299 set_ltb_thresholds : false,
300 set_strategy : ParameterSetStrategy::ControlServer,
301 rat_ltb_thresholds : default_thresholds,
302 }
303 }
304
305 #[cfg(feature="database")]
306 pub fn emit_ltb_settings_packets(&self, rats : &HashMap<u8,RAT>) -> Vec<TofPacket> {
307 let mut packets = Vec::<TofPacket>::new();
308 for k in rats.keys() {
309 let rat = &rats[&k];
310 let rat_key = format!("RAT{:2}", rat);
311 let mut cmd = TofCommand::new();
312 cmd.command_code = TofCommandCode::SetLTBThresholds;
313 let mut payload = LTBThresholdConfig::new();
314 payload.rb_id = rat.rb1_id as u8;
315 if *k as usize >= self.rat_ltb_thresholds.len() {
316 error!("RAT ID {k} larger than 20!");
317 continue;
318 }
319 payload.thresholds = self.rat_ltb_thresholds[&rat_key];
320 cmd.payload = payload.to_bytestream();
321 let tp = cmd.pack();
322 packets.push(tp);
323 }
324 packets
325 }
326}
327
328impl fmt::Display for LTBThresholdSettings {
329 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
330 let disp : String;
331 match toml::to_string(self) {
332 Err(err) => {
333 error!("Deserialization error! {err}");
334 disp = String::from("-- DESERIALIZATION ERROR! --");
335 }
336 Ok(_disp) => {
337 disp = _disp;
338 }
339 }
340 write!(f, "<LTBThresholdSettings :\n{}>", disp)
341 }
342}
343
344impl Default for LTBThresholdSettings {
345 fn default() -> Self {
346 Self::new()
347 }
348}
349
350#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
351pub struct CommandDispatcherSettings {
352 pub cmd_log_path : String,
357 pub cc_server_address : String,
363 pub fc_sub_address : String,
367 pub cmd_listener_interval_sec : u64,
369 pub deny_all_requests : bool
372}
373
374impl CommandDispatcherSettings {
375 pub fn new() -> Self {
376 Self {
377 cmd_log_path : String::from("/home/gaps/log"),
378 cc_server_address : String::from("tcp://10.0.1.10:42000"),
379 fc_sub_address : String::from("tcp://192.168.37.200:41662"),
380 cmd_listener_interval_sec : 1,
381 deny_all_requests : false
382 }
383 }
384}
385
386impl fmt::Display for CommandDispatcherSettings {
387 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
388 let disp = toml::to_string(self).unwrap_or(
389 String::from("-- DESERIALIZATION ERROR! --"));
390 write!(f, "<CommandDispatcherSettings :\n{}>", disp)
391 }
392}
393
394impl Default for CommandDispatcherSettings {
395 fn default() -> Self {
396 Self::new()
397 }
398}
399
400#[derive(Clone, Copy, Debug, PartialEq, serde::Serialize, serde::Deserialize)]
402pub enum RBBufferStrategy {
403 NEvents(u16),
406 NSeconds(f32),
409 ActuallySmart,
412}
413
414impl fmt::Display for RBBufferStrategy {
415 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
416 let r = serde_json::to_string(self).unwrap_or(
417 String::from("N.A. - Invalid RBBufferStrategy (error)"));
418 write!(f, "<RBBufferStrategy: {}>", r)
419 }
420}
421
422
423#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
425pub struct RBSettings {
426 pub only_perfect_events : bool,
430 pub calc_crc32 : bool,
433 pub tof_op_mode : TofOperationMode,
436 pub trigger_poisson_rate : u32,
439 pub trigger_fixed_rate : u32,
442 pub data_type : DataType,
443 pub rb_buff_strategy : HashMap<String,RBBufferStrategy>,
455 pub rb_moni_interval : f32,
458 pub pb_moni_every_x : f32,
460 pub pa_moni_every_x : f32,
462 pub ltb_moni_every_x : f32,
464 pub drs_deadtime_instead_fpga_temp : bool
466}
467
468impl RBSettings {
469 pub fn new() -> Self {
470 let mut rb_buff_strategy = HashMap::<String, RBBufferStrategy>::new();
471 let rb_ids : Vec<u8> = vec![1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,39,40,41,42,46];
472 if rb_ids.len() != 40 {
473 panic!("Something is wrong with the rb ids, we see {} of them!", rb_ids.len());
474 }
475 for k in rb_ids {
476 let key : String = format!("{k}");
477 rb_buff_strategy.insert(key, RBBufferStrategy::ActuallySmart);
478 }
479 Self {
480 only_perfect_events : false,
481 calc_crc32 : false,
482 tof_op_mode : TofOperationMode::Default,
483 trigger_fixed_rate : 0,
484 trigger_poisson_rate : 0,
485 data_type : DataType::Physics,
486 rb_buff_strategy : rb_buff_strategy,
488 rb_moni_interval : 0.0,
489 pb_moni_every_x : 0.0,
490 pa_moni_every_x : 0.0,
491 ltb_moni_every_x : 0.0,
492 drs_deadtime_instead_fpga_temp : false
493 }
494 }
495
496 pub fn from_tofrbconfig(&mut self, cfg : &TofRBConfig) {
497 if cfg.rb_moni_interval.is_some() {
498 self.rb_moni_interval = cfg.rb_moni_interval.unwrap() as f32;
499 }
500 if cfg.rb_moni_interval.is_some() {
501 self.pb_moni_every_x = cfg.pb_moni_every_x.unwrap() as f32;
502 }
503 if cfg.rb_moni_interval.is_some() {
504 self.pa_moni_every_x = cfg.pa_moni_every_x.unwrap() as f32;
505 }
506 if cfg.rb_moni_interval.is_some() {
507 self.ltb_moni_every_x = cfg.ltb_moni_every_x.unwrap() as f32;
508 }
509 if cfg.rb_moni_interval.is_some() {
510 self.drs_deadtime_instead_fpga_temp = cfg.drs_deadtime_instead_fpga_temp.unwrap();
511 }
512 }
513
514 pub fn get_runconfig(&self, board_id : u8) -> RunConfig {
515 let mut rcfg = RunConfig::new();
518 rcfg.is_active = true;
519 rcfg.tof_op_mode = self.tof_op_mode.clone();
520 rcfg.trigger_fixed_rate = self.trigger_fixed_rate;
521 rcfg.trigger_poisson_rate = self.trigger_poisson_rate;
522 rcfg.data_type = self.data_type.clone();
523 let key : String = format!("{board_id}");
524 let buffer_strategy = self.rb_buff_strategy.get(&key).unwrap();
525 match buffer_strategy {
526 RBBufferStrategy::NEvents(buff_size) => {
527 rcfg.rb_buff_size = Some(*buff_size as u16);
528 },
529 RBBufferStrategy::NSeconds(interval) => {
530 rcfg.rb_buff_empty_interval = Some(*interval as f32);
531 },
532 RBBufferStrategy::ActuallySmart => {
533 rcfg.rb_buff_strategy_smart = true;
534 }
535 }
536 rcfg
537 }
538}
539
540impl fmt::Display for RBSettings {
541 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
542 let disp = toml::to_string(self).unwrap_or(
543 String::from("-- DESERIALIZATION ERROR! --"));
544 write!(f, "<RBSettings :\n{}>", disp)
545 }
546}
547
548impl Default for RBSettings {
549 fn default() -> Self {
550 Self::new()
551 }
552}
553
554
555#[derive(Debug, Copy, Clone, serde::Serialize, serde::Deserialize)]
558#[cfg_attr(feature="pybindings", pyclass)]
559pub struct AnalysisEngineSettings {
560 pub integration_start : f32,
562 pub integration_window : f32,
564 pub pedestal_thresh : f32,
566 pub pedestal_begin_bin : usize,
568 pub pedestal_win_bins : usize,
570 pub use_zscore : bool,
573 pub find_pks_t_start : f32,
575 pub find_pks_t_window : f32,
577 pub min_peak_size : usize,
579 pub find_pks_thresh : f32,
581 pub max_peaks : usize,
583 pub cfd_fraction : f32,
585 pub tot_threshold_high : Option<f32>,
588 pub tot_threshold_low : Option<f32>
591}
592
593impl AnalysisEngineSettings {
594 pub fn new() -> Self {
595 Self {
596 integration_start : 270.0,
597 integration_window : 70.0,
598 pedestal_thresh : 10.0,
599 pedestal_begin_bin : 10,
600 pedestal_win_bins : 50,
601 use_zscore : false,
602 find_pks_t_start : 270.0,
603 find_pks_t_window : 70.0,
604 min_peak_size : 3,
605 find_pks_thresh : 10.0,
606 max_peaks : 5,
607 cfd_fraction : 0.2,
608 tot_threshold_low : Some(250.0),
609 tot_threshold_high : Some(750.0),
610 }
611 }
612}
613
614impl fmt::Display for AnalysisEngineSettings {
615 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
616 let disp = toml::to_string(self).unwrap_or(
617 String::from("-- DESERIALIZATION ERROR! --"));
618 write!(f, "<AnalysisEngineSettings :\n{}>", disp)
619 }
620}
621
622impl Default for AnalysisEngineSettings {
623 fn default() -> Self {
624 Self::new()
625 }
626}
627
628#[cfg(feature="pybindings")]
632#[pymethods]
633impl AnalysisEngineSettings {
634
635 #[getter]
636 fn get_integration_start(&self) -> f32 {
637 self.integration_start
638 }
639
640 #[setter]
641 fn set_integration_start(&mut self, value : f32) {
642 self.integration_start = value;
643 }
644
645 #[getter]
646 fn get_integration_window(&self) -> f32 {
647 self.integration_window
648 }
649
650 #[setter]
651 fn set_integration_window(&mut self, value : f32) {
652 self.integration_window = value;
653 }
654
655 #[getter]
656 fn get_pedestal_thresh(&self) -> f32 {
657 self.pedestal_thresh
658 }
659
660 #[setter]
661 fn set_pedestal_thresh(&mut self, value : f32) {
662 self.pedestal_thresh = value;
663 }
664
665 #[getter]
666 fn get_pedestal_begin_bin(&self) -> usize {
667 self.pedestal_begin_bin
668 }
669
670 #[setter]
671 fn set_pedestal_begin_bin(&mut self, value : usize) {
672 self.pedestal_begin_bin = value;
673 }
674
675 #[getter]
676 fn get_pedestal_win_bins(&self) -> usize {
677 self.pedestal_win_bins
678 }
679
680 #[setter]
681 fn set_pedestal_win_bins(&mut self, value : usize) {
682 self.pedestal_win_bins = value;
683 }
684
685 #[getter]
686 fn get_use_zscore(&self) -> bool {
687 self.use_zscore
688 }
689
690 #[setter]
691 fn set_use_zscore(&mut self, value : bool) {
692 self.use_zscore = value;
693 }
694
695 #[getter]
696 fn get_find_pks_t_start(&self) -> f32 {
697 self.find_pks_t_start
698 }
699
700 #[setter]
701 fn set_find_pks_t_start(&mut self, value : f32) {
702 self.find_pks_t_start = value;
703 }
704
705 #[getter]
706 fn get_find_pks_t_window(&self) -> f32 {
707 self.find_pks_t_window
708 }
709
710 #[setter]
711 fn set_find_pks_t_window(&mut self, value : f32) {
712 self.find_pks_t_window = value;
713 }
714
715 #[getter]
716 fn get_min_peak_size(&self) -> usize {
717 self.min_peak_size
718 }
719
720 #[setter]
721 fn set_min_peak_size(&mut self, value : usize) {
722 self.min_peak_size = value;
723 }
724
725 #[getter]
726 fn get_find_pks_thresh(&self) -> f32 {
727 self.find_pks_thresh
728 }
729
730 #[setter]
731 fn set_find_pks_thresh(&mut self, value : f32) {
732 self.find_pks_thresh = value;
733 }
734
735 #[getter]
736 fn get_max_peaks(&self) -> usize {
737 self.max_peaks
738 }
739
740 #[setter]
741 fn set_max_peaks(&mut self, value : usize) {
742 self.max_peaks = value;
743 }
744
745 #[getter]
746 fn get_cfd_fraction(&self) -> f32 {
747 self.cfd_fraction
748 }
749
750 #[setter]
751 fn set_cfd_fraction(&mut self, value : f32) {
752 self.cfd_fraction = value;
753 }
754
755 #[getter]
756 fn get_tot_threshold_low(&self) -> Option<f32> {
757 self.tot_threshold_low
758 }
759
760 #[setter]
761 fn set_tot_threshold_low(&mut self, value : Option<f32>) {
762 self.tot_threshold_low = value;
763 }
764
765 #[getter]
766 fn get_tot_threshold_high(&self) -> Option<f32> {
767 self.tot_threshold_high
768 }
769
770 #[setter]
771 fn set_tot_threshold_high(&mut self, value : Option<f32>) {
772 self.tot_threshold_high = value;
773 }
774}
775
776#[cfg(feature="pybindings")]
779pythonize!(AnalysisEngineSettings);
780
781#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
785pub struct TofEventBuilderSettings {
786 pub cachesize : u32,
787 pub n_mte_per_loop : u32,
788 pub n_rbe_per_loop : u32,
789 pub te_timeout_sec : u32,
792 pub te_timeout_sec_combo : Option<u32>,
795 pub holdoff : Option<u32>,
797 pub sort_events : bool,
799 pub build_strategy : BuildStrategy,
800 pub greediness : u8,
801 pub wait_nrb : u8,
802 pub hb_send_interval : u16,
803 pub no_expect_dead_rbs : Option<bool>,
808 pub ignore_mtb_link_ids : Option<Vec<u8>>,
809 pub only_save_interesting : bool,
813 pub thr_n_hits_umb : Option<u8>,
814 pub thr_n_hits_cbe : Option<u8>,
815 pub thr_n_hits_cor : Option<u8>,
816 pub thr_n_hits_outer : Option<u8>,
817 pub thr_tot_edep_outer : Option<f32>,
818 pub thr_tot_edep_umb : Option<f32>,
819 pub thr_tot_edep_cbe : Option<f32>,
820 pub thr_tot_edep_cor : Option<f32>,
821 pub rbe_purge_limit1 : Option<u32>,
823 pub rbe_purge_limit1_n : Option<u32>,
824 pub rbe_purge_ev_time1 : Option<u32>,
825 pub rbe_purge_limit2 : Option<u32>,
827 pub rbe_purge_limit2_n : Option<i32>,
828 pub rbe_purge_ev_time2 : Option<u32>,
829 pub rbe_purge_limit3 : Option<u32>,
831 pub rbe_purge_limit3_n : Option<i32>,
832 pub rbe_purge_ev_time3 : Option<u32>,
833}
834
835impl TofEventBuilderSettings {
836 pub fn new() -> TofEventBuilderSettings {
837 TofEventBuilderSettings {
838 cachesize : 100000,
839 n_mte_per_loop : 1,
840 n_rbe_per_loop : 40,
841 te_timeout_sec : 30,
842 te_timeout_sec_combo : Some(30),
843 holdoff : Some(0),
844 sort_events : false,
845 build_strategy : BuildStrategy::Adaptive,
846 greediness : 3,
847 wait_nrb : 40,
848 hb_send_interval : 30,
849 only_save_interesting : false,
850 no_expect_dead_rbs : None,
851 ignore_mtb_link_ids : None,
852 thr_n_hits_umb : None,
853 thr_n_hits_cbe : None,
854 thr_n_hits_cor : None,
855 thr_n_hits_outer : None,
856 thr_tot_edep_umb : None,
857 thr_tot_edep_cbe : None,
858 thr_tot_edep_cor : None,
859 thr_tot_edep_outer : None,
860 rbe_purge_limit1 : None,
861 rbe_purge_limit1_n : None,
862 rbe_purge_ev_time1 : None,
863 rbe_purge_limit2 : None,
864 rbe_purge_limit2_n : None,
865 rbe_purge_ev_time2 : None,
866 rbe_purge_limit3 : None,
867 rbe_purge_limit3_n : None,
868 rbe_purge_ev_time3 : None,
869 }
870 }
871
872 }
929
930impl fmt::Display for TofEventBuilderSettings {
931 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
932 let disp = toml::to_string(self).unwrap_or(
933 String::from("-- DESERIALIZATION ERROR! --"));
934 write!(f, "<TofEventBuilderSettings :\n{}>", disp)
935 }
936}
937
938impl Default for TofEventBuilderSettings {
939 fn default() -> Self {
940 Self::new()
941 }
942}
943
944#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
946pub struct DataPublisherSettings {
947 pub data_dir : String,
949 pub mbytes_per_file : usize,
952 pub fc_pub_address : String,
955 pub discard_event_fraction : f32,
959 pub send_mtb_event_packets : bool,
969 pub send_rbwaveform_packets : bool,
972 pub send_rbwf_every_x_event : u32,
975 pub send_tof_summary_packets : bool,
976 pub send_tof_event_packets : bool,
977 pub send_cali_packets : bool,
979 pub hb_send_interval : u16,
980}
981
982impl DataPublisherSettings {
983 pub fn new() -> Self {
984 Self {
985 data_dir : String::from(""),
986 mbytes_per_file : 420,
987 fc_pub_address : String::from(""),
988 discard_event_fraction : 0.0,
989 send_mtb_event_packets : false,
990 send_rbwaveform_packets : false,
991 send_rbwf_every_x_event : 1,
992 send_tof_summary_packets : true,
993 send_tof_event_packets : false,
994 send_cali_packets : true,
995 hb_send_interval : 30,
996 }
997 }
998
999 pub fn from_datapublisherconfig(&mut self, cfg : &DataPublisherConfig) {
1000 if cfg.mbytes_per_file.is_some() {
1001 self.mbytes_per_file = cfg.mbytes_per_file.unwrap() as usize;
1002 }
1003 if cfg.discard_event_fraction.is_some() {
1004 self.discard_event_fraction = cfg.discard_event_fraction.unwrap();
1005 }
1006 if cfg.send_mtb_event_packets.is_some() {
1007 self.send_mtb_event_packets = cfg.send_mtb_event_packets.unwrap();
1008 }
1009 if cfg.send_rbwaveform_packets.is_some() {
1010 self.send_rbwaveform_packets = cfg.send_rbwaveform_packets.unwrap();
1011 }
1012 if cfg.send_rbwf_every_x_event.is_some() {
1013 self.send_rbwf_every_x_event = cfg.send_rbwf_every_x_event.unwrap();
1014 }
1015 if cfg.send_tof_summary_packets.is_some() {
1016 self.send_tof_summary_packets = cfg.send_tof_summary_packets.unwrap();
1017 }
1018 if cfg.send_tof_event_packets.is_some() {
1019 self.send_tof_event_packets = cfg.send_tof_event_packets.unwrap();
1020 }
1021 if cfg.hb_send_interval.is_some() {
1022 self.hb_send_interval = cfg.hb_send_interval.unwrap();
1023 }
1024 }
1025}
1026
1027impl fmt::Display for DataPublisherSettings {
1028 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1029 let disp = toml::to_string(self).unwrap_or(
1030 String::from("-- DESERIALIZATION ERROR! --"));
1031 write!(f, "<DataPublisherSettings :\n{}>", disp)
1032 }
1033}
1034
1035impl Default for DataPublisherSettings {
1036 fn default() -> Self {
1037 Self::new()
1038 }
1039}
1040
1041
1042#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
1043#[cfg_attr(feature="pybindings", pyclass)]
1044pub struct LiftofSettings {
1045 pub config_version : Option<String>,
1048 pub staging_dir : String,
1051 pub calibration_dir : String,
1053 pub db_path : String,
1055 pub runtime_sec : u64,
1057 pub mtb_address : String,
1060 pub cpu_moni_interval_sec : u64,
1063 pub rb_ignorelist_always : Vec<u8>,
1066 pub rb_ignorelist_run : Vec<u8>,
1068 pub run_analysis_engine : bool,
1070 pub rb_controls_pb_and_ltb : Option<Vec<u8>>,
1072 pub pre_run_calibration : bool,
1075 pub save_cali_wf : bool,
1078 pub verification_run : Option<bool>,
1088 pub mtb_settings : MTBSettings,
1090 pub event_builder_settings : TofEventBuilderSettings,
1092 pub analysis_engine_settings : AnalysisEngineSettings,
1094 pub data_publisher_settings : DataPublisherSettings,
1096 pub cmd_dispatcher_settings : CommandDispatcherSettings,
1098 pub rb_settings : RBSettings,
1100 pub rb_channel_mask : ChannelMaskSettings,
1103 pub preamp_settings : PreampSettings,
1105 pub ltb_settings : LTBThresholdSettings
1107}
1108
1109impl LiftofSettings {
1110 pub fn new() -> Self {
1111 LiftofSettings {
1112 config_version : None,
1113 staging_dir : String::from("/home/gaps/liftof-staging"),
1114 calibration_dir : String::from(""),
1115 db_path : String::from("/home/gaps/config/gaps_flight.db"),
1116 runtime_sec : 0,
1117 mtb_address : String::from("10.0.1.10:50001"),
1118 cpu_moni_interval_sec : 60,
1119 rb_ignorelist_always : Vec::<u8>::new(),
1120 rb_ignorelist_run : Vec::<u8>::new(),
1121 rb_controls_pb_and_ltb : None,
1122 run_analysis_engine : true,
1123 pre_run_calibration : false,
1124 save_cali_wf : false,
1125 verification_run : None,
1127 mtb_settings : MTBSettings::new(),
1128 event_builder_settings : TofEventBuilderSettings::new(),
1129 analysis_engine_settings : AnalysisEngineSettings::new(),
1130 data_publisher_settings : DataPublisherSettings::new(),
1131 cmd_dispatcher_settings : CommandDispatcherSettings::new(),
1132 rb_settings : RBSettings::new(),
1133 rb_channel_mask : ChannelMaskSettings::new(),
1134 preamp_settings : PreampSettings::new(),
1135 ltb_settings : LTBThresholdSettings::new(),
1136 }
1137 }
1138
1139 pub fn from_tofrunconfig(&mut self, cfg : &TofRunConfig) {
1142 if cfg.runtime.is_some() {
1143 self.runtime_sec = cfg.runtime.unwrap() as u64;
1144 }
1145 }
1146
1147 pub fn to_toml(&self, mut filename : String) {
1149 if !filename.ends_with(".toml") {
1150 filename += ".toml";
1151 }
1152 info!("Will write to file {}!", filename);
1153 match File::create(&filename) {
1154 Err(err) => {
1155 error!("Unable to open file {}! {}", filename, err);
1156 }
1157 Ok(mut file) => {
1158 match toml::to_string_pretty(&self) {
1159 Err(err) => {
1160 error!("Unable to serialize toml! {err}");
1161 }
1162 Ok(toml_string) => {
1163 match file.write_all(toml_string.as_bytes()) {
1164 Err(err) => error!("Unable to write to file {}! {}", filename, err),
1165 Ok(_) => debug!("Wrote settings to {}!", filename)
1166 }
1167 }
1168 }
1169 }
1170 }
1171 }
1172
1173 pub fn to_json(&self, mut filename : String) {
1175 if !filename.ends_with(".json") {
1176 filename += ".json";
1177 }
1178 info!("Will write to file {}!", filename);
1179 match File::create(&filename) {
1180 Err(err) => {
1181 error!("Unable to open file {}! {}", filename, err);
1182 }
1183 Ok(file) => {
1184 match serde_json::to_writer_pretty(file, &self) {
1185 Err(err) => {
1186 error!("Unable to serialize json! {err}");
1187 }
1188 Ok(_) => debug!("Wrote settings to {}!", filename)
1189 }
1190 }
1191 }
1192 }
1193
1194 pub fn from_toml(filename : &str) -> Result<LiftofSettings, SerializationError> {
1195 match File::open(filename) {
1196 Err(err) => {
1197 error!("Unable to open {}! {}", filename, err);
1198 return Err(SerializationError::TomlDecodingError);
1199 }
1200 Ok(mut file) => {
1201 let mut toml_string = String::from("");
1202 match file.read_to_string(&mut toml_string) {
1203 Err(err) => {
1204 error!("Unable to read {}! {}", filename, err);
1205 return Err(SerializationError::TomlDecodingError);
1206 }
1207 Ok(_) => {
1208 match toml::from_str(&toml_string) {
1209 Err(err) => {
1210 error!("Can't interpret toml! {}", err);
1211 return Err(SerializationError::TomlDecodingError);
1212 }
1213 Ok(settings) => {
1214 return Ok(settings);
1215 }
1216 }
1217 }
1218 }
1219 }
1220 }
1221 }
1222}
1223
1224impl fmt::Display for LiftofSettings {
1225 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1226 let disp : String;
1227 match toml::to_string(self) {
1228 Err(err) => {
1229 println!("Deserialization error! {err}");
1230 disp = String::from("-- DESERIALIZATION ERROR! --");
1231 }
1232 Ok(_disp) => {
1233 disp = _disp;
1234 }
1235 }
1236 write!(f, "<LiftofSettings :\n{}>", disp)
1237 }
1238}
1239
1240impl Default for LiftofSettings {
1241 fn default() -> Self {
1242 Self::new()
1243 }
1244}
1245
1246#[cfg(feature="pybindings")]
1247#[pymethods]
1248impl LiftofSettings {
1249
1250 #[staticmethod]
1257 fn from_file(filename : &str) -> PyResult<Self> {
1258 match LiftofSettings::from_toml(filename) {
1259 Ok(settings) => {
1260 return Ok(settings);
1261 }
1262 Err(err) => {
1263 return Err(PyValueError::new_err(err.to_string()));
1264 }
1265 }
1266 }
1267}
1268
1269#[cfg(feature="pybindings")]
1270pythonize!(LiftofSettings);
1271
1272#[derive(Debug, Copy, Clone, PartialEq, serde::Deserialize, serde::Serialize)]
1276pub struct LiftofRBConfig {
1277 pub nseconds : u32,
1279 pub tof_op_mode : TofOperationMode,
1282 pub trigger_poisson_rate : u32,
1285 pub trigger_fixed_rate : u32,
1288 pub data_type : DataType,
1292 pub rb_buff_size : u16
1298}
1299
1300impl LiftofRBConfig {
1301
1302 pub fn new() -> Self {
1303 Self {
1304 nseconds : 0,
1305 tof_op_mode : TofOperationMode::Default,
1306 trigger_poisson_rate : 0,
1307 trigger_fixed_rate : 0,
1308 data_type : DataType::Unknown,
1309 rb_buff_size : 0,
1310 }
1311 }
1312}
1313
1314impl Serialization for LiftofRBConfig {
1315 const HEAD : u16 = 43690; const TAIL : u16 = 21845; const SIZE : usize = 24; fn from_bytestream(bytestream : &Vec<u8>,
1320 pos : &mut usize)
1321 -> Result<Self, SerializationError> {
1322 let mut pars = Self::new();
1323 Self::verify_fixed(bytestream, pos)?;
1324 pars.nseconds = parse_u32 (bytestream, pos);
1325 pars.tof_op_mode
1326 = TofOperationMode::try_from(
1327 parse_u8(bytestream, pos))
1328 .unwrap_or_else(|_| TofOperationMode::Unknown);
1329 pars.trigger_poisson_rate = parse_u32 (bytestream, pos);
1330 pars.trigger_fixed_rate = parse_u32 (bytestream, pos);
1331 pars.data_type
1332 = DataType::try_from(parse_u8(bytestream, pos))
1333 .unwrap_or_else(|_| DataType::Unknown);
1334 pars.rb_buff_size = parse_u16(bytestream, pos);
1335 *pos += 2; Ok(pars)
1338 }
1339
1340 fn to_bytestream(&self) -> Vec<u8> {
1341 let mut stream = Vec::<u8>::with_capacity(Self::SIZE);
1342 stream.extend_from_slice(&Self::HEAD.to_le_bytes());
1343 stream.extend_from_slice(&self. nseconds.to_le_bytes());
1344 stream.extend_from_slice(&(self.tof_op_mode as u8).to_le_bytes());
1345 stream.extend_from_slice(&self.trigger_poisson_rate.to_le_bytes());
1346 stream.extend_from_slice(&self.trigger_fixed_rate.to_le_bytes());
1347 stream.extend_from_slice(&(self.data_type as u8).to_le_bytes());
1348 stream.extend_from_slice(&self.rb_buff_size.to_le_bytes());
1349 stream.extend_from_slice(&Self::TAIL.to_le_bytes());
1350 stream
1351 }
1352}
1353
1354impl Default for LiftofRBConfig {
1355 fn default() -> Self {
1356 Self::new()
1357 }
1358}
1359
1360impl fmt::Display for LiftofRBConfig {
1361 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1362 write!(f,
1363"<LiftofRBConfig -- is_active : true
1364 nseconds : {}
1365 TOF op. mode : {}
1366 data type : {}
1367 tr_poi_rate : {}
1368 tr_fix_rate : {}
1369 buff size : {} [events]>",
1370 self.nseconds,
1371 self.tof_op_mode,
1372 self.data_type,
1373 self.trigger_poisson_rate,
1374 self.trigger_fixed_rate,
1375 self.rb_buff_size)
1376 }
1377}
1378
1379#[derive(Debug, Clone, serde::Deserialize, serde::Serialize)]
1395pub struct ChannelMaskSettings {
1396 pub set_channel_mask : bool,
1398 pub set_strategy : ParameterSetStrategy,
1404 pub rb_channel_mask : HashMap<String, [bool;9]>
1408}
1409
1410impl ChannelMaskSettings {
1411 pub fn new() -> Self {
1412 let mut default_thresholds = HashMap::<String, [bool; 9]>::new();
1413 for k in 1..51 {
1414 let key = format!("RB{k:02}");
1415 default_thresholds.insert(key, [true;9]);
1416 }
1417Self {
1440 set_channel_mask : false,
1441 set_strategy : ParameterSetStrategy::ControlServer,
1442 rb_channel_mask : default_thresholds,
1443 }
1444 }
1445
1446 #[cfg(feature="database")]
1447 pub fn emit_ch_mask_packets(&self, rbs : &HashMap<u8,RAT>) -> Vec<TofPacket> {
1448 let mut packets = Vec::<TofPacket>::new();
1449 for k in rbs.keys() {
1450 let rb = &rbs[&k];
1451 let rb_key = format!("RB{:2}", rb);
1452 let mut cmd = TofCommand::new();
1453 cmd.command_code = TofCommandCode::SetRBChannelMask;
1454 let mut payload = RBChannelMaskConfig::new();
1455 payload.rb_id = rb.rb2_id as u8;
1456 if *k as usize >= self.rb_channel_mask.len() {
1457 error!("RB ID {k} larger than 46!");
1458 continue;
1459 }
1460 payload.channels = self.rb_channel_mask[&rb_key];
1461 cmd.payload = payload.to_bytestream();
1462 let tp = cmd.pack();
1463 packets.push(tp);
1464 }
1465 packets
1466 }
1467}
1468impl fmt::Display for ChannelMaskSettings {
1469 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1470 let disp : String;
1471 match toml::to_string(self) {
1472 Err(err) => {
1473 error!("Deserialization error! {err}");
1474 disp = String::from("-- DESERIALIZATION ERROR! --");
1475 }
1476 Ok(_disp) => {
1477 disp = _disp;
1478 }
1479 }
1480 write!(f, "<RBChannelMaskConfig :\n{}>", disp)
1481 }
1482}
1483
1484impl Default for ChannelMaskSettings {
1485 fn default() -> Self {
1486 Self::new()
1487 }
1488}
1489
1490#[cfg(feature="random")]
1491#[test]
1492fn mtb_config() {
1493
1494 for _ in 0..100 {
1495 let cfg = TriggerConfig::from_random();
1496 let mut settings = MTBSettings::new();
1497 settings.from_triggerconfig(&cfg);
1498 let test = settings.emit_triggerconfig();
1499 if cfg.gaps_trigger_use_beta.is_some() {
1500 assert_eq!(cfg.gaps_trigger_use_beta, test.gaps_trigger_use_beta);
1501 }
1502 if cfg.prescale.is_some() {
1503 assert_eq!(cfg.prescale, test.prescale);
1504 }
1505 if cfg.trigger_type.is_some() {
1506 assert_eq!(cfg.trigger_type, test.trigger_type);
1507 }
1508 if cfg.use_combo_trigger.is_some() {
1509 assert_eq!(cfg.use_combo_trigger, test.use_combo_trigger);
1510 }
1511 if cfg.combo_trigger_type.is_some() {
1512 assert_eq!(cfg.combo_trigger_type, test.combo_trigger_type);
1513 }
1514 if cfg.combo_trigger_prescale.is_some() {
1515 assert_eq!(cfg.combo_trigger_prescale, test.combo_trigger_prescale);
1516 }
1517 if cfg.trace_suppression.is_some() {
1518 assert_eq!(cfg.trace_suppression, test.trace_suppression);
1519 }
1520 if cfg.mtb_moni_interval.is_some() {
1521 assert_eq!(cfg.mtb_moni_interval, test.mtb_moni_interval);
1522 }
1523 if cfg.tiu_ignore_busy.is_some() {
1524 assert_eq!(cfg.tiu_ignore_busy, test.tiu_ignore_busy);
1525 }
1526 if cfg.hb_send_interval.is_some() {
1527 assert_eq!(cfg.hb_send_interval, test.hb_send_interval);
1528 }
1529 }
1530}
1531
1532#[test]
1533fn write_config_file() {
1534 let settings = LiftofSettings::new();
1535 settings.to_toml(String::from("liftof-config-test.toml"));
1537}
1538
1539#[test]
1540fn compress_uncompress_config_file() {
1541 write_config_file();
1542 let pth = Path::new("liftof-config-test.toml");
1543 let bytestream = compress_toml(&pth).unwrap();
1544 println!("Compressed .toml file to a bytestream of {} bytes!", bytestream.len());
1545 let output = Path::new("liftof-config-decompressed.toml");
1546 decompress_toml(&bytestream.as_slice(), output);
1547}
1548
1549#[test]
1550fn diff_config_file_compress_uncompress() {
1551 write_config_file();
1552 let mut settings = LiftofSettings::new();
1553 settings.to_toml(String::from("liftof-config-test.toml"));
1554 settings.staging_dir = String::from("/foo/bar");
1555 settings.to_toml(String::from("liftof-config-test-changed.toml"));
1556 let pth = Path::new("liftof-config-test.toml");
1557 let pth_ch = Path::new("liftof-config-test-changed.toml");
1558 let diff = create_compressed_diff(&pth, &pth_ch).unwrap();
1559 println!("Diff has the size of {} bytes!", diff.len());
1560 let output = Path::new("liftof-config.diff");
1561 decompress_toml(&diff.as_slice(), output);
1562}
1563
1564#[test]
1565fn read_config_file() {
1566 let _settings = LiftofSettings::from_toml("liftof-config-test.toml");
1567}
1568
1569