alpha_g_physics/calibration/pads/
baseline.rs

1use alpha_g_detector::padwing::map::TpcPadPosition;
2use lazy_static::lazy_static;
3use std::collections::HashMap;
4use thiserror::Error;
5
6includes! {
7    DATA_PATH = "../../../data/calibration/pads/baseline/";
8    // All the following files are embedded at compile time.
9    // Add new files to the list below.
10    BYTES_SIMULATION = "simulation_complete.ron",
11    BYTES_9277 = "9277_complete_handwritten_cherry_picked_see_commit.ron",
12    BYTES_11192 = "11192_complete.ron",
13}
14
15lazy_static! {
16    // Whenever a new file is added, generate the appropriate new HashMap.
17    // Do not delete any of the existing maps.
18    //
19    // Adding a new map is as simple as either:
20    // complete_from_bytes(BYTES_NUMBER)
21    // or
22    // update_previous_from_bytes(&PREVIOUS_HASHMAP, BYTES_NUMBER)
23    static ref MAP_SIMULATION: HashMap<TpcPadPosition, i16> = complete_from_bytes(BYTES_SIMULATION);
24    static ref MAP_9277: HashMap<TpcPadPosition, i16> = complete_from_bytes(BYTES_9277);
25    static ref MAP_11192: HashMap<TpcPadPosition, i16> = complete_from_bytes(BYTES_11192);
26}
27
28/// Try to get the baseline for a given pad. Return an error if there is no map
29/// available for the given run number or if there is no baseline for the given
30/// pad in the map.
31pub(crate) fn try_pad_baseline(
32    run_number: u32,
33    pad: TpcPadPosition,
34) -> Result<i16, MapPadBaselineError> {
35    // This map should be updated whenever a new file is added.
36    let map = match run_number {
37        // u32::MAX corresponds to a simulation run.
38        u32::MAX => &*MAP_SIMULATION,
39        // The calibration was done on run 11192. But the detector was in this
40        // configuration since it was turned on in run 11084.
41        11084.. => &*MAP_11192,
42        9277.. => &*MAP_9277,
43        _ => return Err(MapPadBaselineError::MissingMap { run_number }),
44    };
45
46    map.get(&pad)
47        .copied()
48        .ok_or(MapPadBaselineError::MissingPad { run_number, pad })
49}
50
51// Nothing below this line needs to be changed when adding a new file.
52
53/// The error type returned when the baseline calibration map is not available.
54#[derive(Debug, Error)]
55pub enum MapPadBaselineError {
56    #[error("no pad baseline calibration available for run number `{run_number}`")]
57    MissingMap { run_number: u32 },
58    #[error("no baseline available for pad `{pad:?}` in run number `{run_number}`")]
59    MissingPad {
60        run_number: u32,
61        pad: TpcPadPosition,
62    },
63}
64
65fn complete_from_bytes(bytes: &[u8]) -> HashMap<TpcPadPosition, i16> {
66    // Correctness of the format is checked by unit tests.
67    let map: HashMap<TpcPadPosition, (f64, f64, usize)> = ron::de::from_bytes(bytes).unwrap();
68
69    map.into_iter()
70        .map(|(pad, (baseline, _, _))| (pad, baseline.round() as i16))
71        .collect()
72}
73
74// Implement `update_previous_from_bytes` whenever I need it for the first time.
75// The implementation would just be a copy-paste of the anode wires calibration.
76// I don't need it now, so I just want to implement it whenever I have a use
77// case to add unit tests for it.
78
79#[cfg(test)]
80mod tests;