fastpasta/analyze/validators/its/
alpide.rs1pub mod alpide_readout_frame;
6pub mod lane_alpide_frame_analyzer;
7
8use crate::util::*;
9
10struct ValidatedLane {
12 lane_id: u8,
13 bunch_counter: u8,
14}
15
16pub fn check_alpide_data_frame(
20 alpide_readout_frame: &AlpideReadoutFrame,
21 custom_checks: &'static impl CustomChecksOpt,
22) -> (Vec<u8>, Vec<String>, AlpideStats, Option<Vec<u8>>) {
23 let mut lane_error_msgs: Vec<String> = Vec::new();
24 let mut lane_error_ids: Vec<u8> = Vec::new();
25 let mut validated_lanes: Vec<ValidatedLane> = Vec::new();
26 let mut fatal_lanes: Option<Vec<u8>> = None;
27
28 let frame_from_layer = alpide_readout_frame.from_layer();
29
30 let mut total_alpide_stats = AlpideStats::default();
31
32 alpide_readout_frame
33 .lane_data_frames_as_slice()
34 .iter()
35 .for_each(|lane_data_frame| {
36 let mut analyzer = LaneAlpideFrameAnalyzer::new(
39 frame_from_layer,
40 custom_checks.chip_orders_ob(),
41 custom_checks.chip_count_ob(),
42 );
43
44 let lane_number = lane_data_frame.lane_number(frame_from_layer);
45 log::trace!("Processing lane #{lane_number}");
46
47 if let Err(mut error_msgs) = analyzer.analyze_alpide_frame(lane_data_frame) {
48 error_msgs.insert_str(0, &format!("\n\tLane {lane_number} errors: "));
49 lane_error_msgs.push(error_msgs);
50 lane_error_ids.push(lane_number);
51 } else if analyzer.is_fatal_lane() {
52 log::warn!("Lane {lane_number} is in FATAL state, now expecting 1 fewer lane in data frames");
53 if fatal_lanes.is_none() {
54 fatal_lanes = Some(Vec::new());
55 }
56 fatal_lanes.as_mut().unwrap().push(lane_number);
57 } else {
58 validated_lanes.push(ValidatedLane {
60 lane_id: lane_number,
61 bunch_counter: analyzer
62 .validated_bc()
63 .expect("No validated bunch counter in lane readout frame with no errors"),
64 });
65 }
66 total_alpide_stats.sum(*analyzer.alpide_stats()); });
68
69 validate_lane_bcs(&validated_lanes, &mut lane_error_msgs, &mut lane_error_ids);
71
72 (
73 lane_error_ids,
74 lane_error_msgs,
75 total_alpide_stats,
76 fatal_lanes,
77 )
78}
79
80fn validate_lane_bcs(
82 validated_lanes: &[ValidatedLane],
83 lane_error_msgs: &mut Vec<String>, lane_error_ids: &mut Vec<u8>, ) {
86 let unique_bunch_counters: Vec<u8> = validated_lanes
87 .iter()
88 .map(|lane| lane.bunch_counter)
89 .collect::<Vec<u8>>()
90 .into_iter()
91 .unique()
92 .collect();
93 if unique_bunch_counters.len() > 1 {
94 let mut error_string = format!(
95 "\n\tLane {:?} error: Mismatching bunch counters between lanes in same readout frame",
96 validated_lanes
97 .iter()
98 .map(|lane| lane.lane_id)
99 .collect::<Vec<u8>>()
100 );
101 let mut lanes_to_bunch_counter: Vec<(u8, Vec<u8>)> = Vec::new();
103 unique_bunch_counters.iter().for_each(|bunch_counter| {
105 lanes_to_bunch_counter.push((
107 *bunch_counter,
108 validated_lanes
109 .iter()
110 .filter(|lane| lane.bunch_counter == *bunch_counter)
111 .map(|lane| lane.lane_id)
112 .collect::<Vec<u8>>(),
113 ));
114 });
115 if !Cfg::global().mute_errors() {
116 add_context_to_unique_bc_error_msg(&lanes_to_bunch_counter, &mut error_string);
117 }
118
119 lane_error_msgs.push(error_string);
120 lane_error_ids.extend(lanes_to_bunch_counter.iter().flat_map(|(_, lanes)| lanes));
121 }
122}
123
124fn add_context_to_unique_bc_error_msg(
125 lanes_to_bunch_counter: &[(u8, Vec<u8>)],
126 error_string: &mut String,
127) {
128 lanes_to_bunch_counter
130 .iter()
131 .for_each(|(bunch_counter, lanes)| {
132 error_string.push_str(&format!(
133 "\n\t\tBunch counter: {bunch_counter:>3?} | Lanes: {lanes:?}",
134 bunch_counter = bunch_counter,
135 lanes = lanes
136 ));
137 });
138}