use crate::util::*;
#[derive(Debug, PartialEq, Clone, Copy, Default, Deserialize, Serialize)]
pub struct TriggerStats {
orbit: u32,
hb: u32,
hbr: u32,
hc: u32,
pht: u32,
pp: u32,
cal: u32,
sot: u32,
eot: u32,
soc: u32,
eoc: u32,
tf: u32,
fe_rst: u32,
rt: u32,
rs: u32,
lhc_gap1: u32,
lhc_gap2: u32,
tpc_sync: u32,
tpc_rst: u32,
tof: u32,
}
impl TriggerStats {
pub fn collect_stats(&mut self, trigger: u32) {
self.orbit += (trigger & 0b0000_0000_0000_0000_0000_0000_0000_0001 != 0) as u32;
self.hb += (trigger & 0b0000_0000_0000_0000_0000_0000_0000_0010 != 0) as u32;
self.hbr += (trigger & 0b0000_0000_0000_0000_0000_0000_0000_0100 != 0) as u32;
self.hc += (trigger & 0b0000_0000_0000_0000_0000_0000_0000_1000 != 0) as u32;
self.pht += (trigger & 0b0000_0000_0000_0000_0000_0000_0001_0000 != 0) as u32;
self.pp += (trigger & 0b0000_0000_0000_0000_0000_0000_0010_0000 != 0) as u32;
self.cal += (trigger & 0b0000_0000_0000_0000_0000_0000_0100_0000 != 0) as u32;
self.sot += (trigger & 0b0000_0000_0000_0000_0000_0000_1000_0000 != 0) as u32;
self.eot += (trigger & 0b0000_0000_0000_0000_0000_0001_0000_0000 != 0) as u32;
self.soc += (trigger & 0b0000_0000_0000_0000_0000_0010_0000_0000 != 0) as u32;
self.eoc += (trigger & 0b0000_0000_0000_0000_0000_0100_0000_0000 != 0) as u32;
self.tf += (trigger & 0b0000_0000_0000_0000_0000_1000_0000_0000 != 0) as u32;
self.fe_rst += (trigger & 0b0000_0000_0000_0000_0001_0000_0000_0000 != 0) as u32;
self.rt += (trigger & 0b0000_0000_0000_0000_0010_0000_0000_0000 != 0) as u32;
self.rs += (trigger & 0b0000_0000_0000_0000_0100_0000_0000_0000 != 0) as u32;
self.lhc_gap1 += (trigger & 0b0000_1000_0000_0000_0000_0000_0000_0000 != 0) as u32;
self.lhc_gap2 += (trigger & 0b0001_0000_0000_0000_0000_0000_0000_0000 != 0) as u32;
self.tpc_sync += (trigger & 0b0010_0000_0000_0000_0000_0000_0000_0000 != 0) as u32;
self.tpc_rst += (trigger & 0b0100_0000_0000_0000_0000_0000_0000_0000 != 0) as u32;
self.tof += (trigger & 0b1000_0000_0000_0000_0000_0000_0000_0000 != 0) as u32;
}
pub fn orbit(&self) -> u32 {
self.orbit
}
pub fn hb(&self) -> u32 {
self.hb
}
pub fn hbr(&self) -> u32 {
self.hbr
}
pub fn hc(&self) -> u32 {
self.hc
}
pub fn pht(&self) -> u32 {
self.pht
}
pub fn pp(&self) -> u32 {
self.pp
}
pub fn cal(&self) -> u32 {
self.cal
}
pub fn sot(&self) -> u32 {
self.sot
}
pub fn eot(&self) -> u32 {
self.eot
}
pub fn soc(&self) -> u32 {
self.soc
}
pub fn eoc(&self) -> u32 {
self.eoc
}
pub fn tf(&self) -> u32 {
self.tf
}
pub fn fe_rst(&self) -> u32 {
self.fe_rst
}
pub fn rt(&self) -> u32 {
self.rt
}
pub fn rs(&self) -> u32 {
self.rs
}
pub fn lhc_gap1(&self) -> u32 {
self.lhc_gap1
}
pub fn lhc_gap2(&self) -> u32 {
self.lhc_gap2
}
pub fn tpc_sync(&self) -> u32 {
self.tpc_sync
}
pub fn tpc_rst(&self) -> u32 {
self.tpc_rst
}
pub fn tof(&self) -> u32 {
self.tof
}
pub(super) fn validate_other(&self, other: &Self) -> Result<(), Vec<String>> {
let other = Self {
orbit: other.orbit(),
hb: other.hb(),
hbr: other.hbr(),
hc: other.hc(),
pht: other.pht(),
pp: other.pp(),
cal: other.cal(),
sot: other.sot(),
eot: other.eot(),
soc: other.soc(),
eoc: other.eoc(),
tf: other.tf(),
fe_rst: other.fe_rst(),
rt: other.rt(),
rs: other.rs(),
lhc_gap1: other.lhc_gap1(),
lhc_gap2: other.lhc_gap2(),
tpc_sync: other.tpc_sync(),
tpc_rst: other.tpc_rst(),
tof: other.tof(),
};
self.validate_fields(&other)
}
crate::validate_fields!(
TriggerStats,
orbit,
hb,
hbr,
hc,
pht,
pp,
cal,
sot,
eot,
soc,
eoc,
tf,
fe_rst,
rt,
rs,
lhc_gap1,
lhc_gap2,
tpc_sync,
tpc_rst,
tof
);
}
impl fmt::Display for TriggerStats {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "Trigger statistics:")?;
writeln!(f, " Orbit: {:>6}", self.orbit)?;
writeln!(f, " HB: {:>6}", self.hb)?;
writeln!(f, " HBr: {:>6}", self.hbr)?;
writeln!(f, " HC: {:>6}", self.hc)?;
writeln!(f, " PhT: {:>6}", self.pht)?;
writeln!(f, " PP: {:>6}", self.pp)?;
writeln!(f, " CAL: {:>6}", self.cal)?;
writeln!(f, " SOT: {:>6}", self.sot)?;
writeln!(f, " EOT: {:>6}", self.eot)?;
writeln!(f, " SOC: {:>6}", self.soc)?;
writeln!(f, " EOC: {:>6}", self.eoc)?;
writeln!(f, " TF: {:>6}", self.tf)?;
writeln!(f, " FE_rst: {:>6}", self.fe_rst)?;
writeln!(f, " RT: {:>6}", self.rt)?;
writeln!(f, " RS: {:>6}", self.rs)?;
writeln!(f, " LHC_gap1: {:>6}", self.lhc_gap1)?;
writeln!(f, " LHC_gap2: {:>6}", self.lhc_gap2)?;
writeln!(f, " TPC_sync: {:>6}", self.tpc_sync)?;
writeln!(f, " TPC_rst: {:>6}", self.tpc_rst)?;
writeln!(f, " TOF: {:>6}", self.tof)?;
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
use pretty_assertions::assert_eq;
#[test]
fn test_serde_consistency() {
let mut trigger_stats = TriggerStats::default();
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_0000_0001);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_0000_0010);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_0000_0100);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_0000_1000);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_0001_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_0010_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_0100_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_1000_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0001_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0010_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0100_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_1000_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0001_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0010_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0100_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0000_1000_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0001_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0010_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0000_0100_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0000_1000_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0001_0000_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0010_0000_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0000_0100_0000_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0000_1000_0000_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0001_0000_0000_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0010_0000_0000_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0000_0100_0000_0000_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0000_1000_0000_0000_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0001_0000_0000_0000_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0010_0000_0000_0000_0000_0000_0000_0000);
trigger_stats.collect_stats(0b0100_0000_0000_0000_0000_0000_0000_0000);
trigger_stats.collect_stats(0b1000_0000_0000_0000_0000_0000_0000_0000);
let trigger_stats_ser_json = serde_json::to_string(&trigger_stats).unwrap();
let trigger_stats_de_json: TriggerStats =
serde_json::from_str(&trigger_stats_ser_json).unwrap();
assert_eq!(trigger_stats, trigger_stats_de_json);
let trigger_stats_ser_toml = toml::to_string(&trigger_stats).unwrap();
let trigger_stats_de_toml: TriggerStats = toml::from_str(&trigger_stats_ser_toml).unwrap();
assert_eq!(trigger_stats, trigger_stats_de_toml);
println!("{trigger_stats_ser_json}");
println!("{trigger_stats_ser_toml}");
assert_eq!(trigger_stats.orbit(), 1);
assert_eq!(trigger_stats.hb(), 1);
assert_eq!(trigger_stats.hbr(), 1);
assert_eq!(trigger_stats.hc(), 1);
assert_eq!(trigger_stats.pht(), 1);
assert_eq!(trigger_stats.pp(), 1);
assert_eq!(trigger_stats.cal(), 1);
assert_eq!(trigger_stats.sot(), 1);
assert_eq!(trigger_stats.eot(), 1);
assert_eq!(trigger_stats.soc(), 1);
assert_eq!(trigger_stats.eoc(), 1);
assert_eq!(trigger_stats.tf(), 1);
assert_eq!(trigger_stats.fe_rst(), 1);
assert_eq!(trigger_stats.rt(), 1);
assert_eq!(trigger_stats.rs(), 1);
assert_eq!(trigger_stats.lhc_gap1(), 1);
assert_eq!(trigger_stats.lhc_gap2(), 1);
assert_eq!(trigger_stats.tpc_sync(), 1);
assert_eq!(trigger_stats.tpc_rst(), 1);
assert_eq!(trigger_stats.tof(), 1);
}
#[test]
fn test_validate_other_success() {
let trigger_stats = TriggerStats::default();
let other_trigger_stats = TriggerStats::default();
if let Err(msg) = trigger_stats.validate_other(&other_trigger_stats) {
panic!("{}", msg.join("\n"));
}
}
#[test]
fn test_validate_other_fails() {
let mut trigger_stats = TriggerStats::default();
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_0000_0001);
let trigger_stats_other = TriggerStats::default();
if let Err(msg) = trigger_stats.validate_other(&trigger_stats_other) {
println!("{}", msg.join("\n"));
} else {
panic!("Validation succeeded, but should have failed!")
}
}
#[test]
fn test_validate_other_multiple_fails() {
let mut trigger_stats = TriggerStats::default();
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_0000_0001);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_0000_0010);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_0000_0100);
trigger_stats.collect_stats(0b0000_0000_0000_0000_0000_0000_0000_1000);
let other_trigger_stats = TriggerStats::default();
if let Err(msg) = trigger_stats.validate_other(&other_trigger_stats) {
println!("{}", msg.join("\n"));
assert!(msg.len() == 4);
} else {
panic!("Validation succeeded, but should have failed!")
}
}
}