From 151b2c9d4ff89bd9923bbc67477896c1a6a5bc1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Thu, 9 Oct 2025 04:05:54 -0500 Subject: [PATCH 01/75] Setup to start extended fragments feature --- .../XARAPUCA/SBNDXARAPUCADecoder_module.cc | 21 ++++++++++--------- .../Decoders/XARAPUCA/xarapucadecoder.fcl | 8 +++---- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index ac94c56e1..5be0a9e5d 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -372,15 +372,15 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) } /** -* @brief Searches for the SPEC-TDC ETRIG timestamp closest to the raw timestamp if any SPEC-TDC ETRIG product is found in the event. -* @param[in] e The event to be processed. -* @param[in] corr_raw_timestamp The corrected raw timestamp from the artdaq::RawEventHeader product. -* @param[in,out] timestamp The closest ETRIG timestamp to the raw timestamp (if found). -* @return A boolean indicating if a valid ETRIG timestamp was found close enough to the raw timestamp. -* @details It searches for the SPEC-TDC products in the event and looks for the ETRIG timestamps. If any ETRIG -* timestamp is found, it checks which one is the closest to the raw timestamp and if it is close enough (i.e. -* within fraw_trig_max_diff) it returns it as output. -*/ + * @brief Searches for the SPEC-TDC ETRIG timestamp closest to the raw timestamp if any SPEC-TDC ETRIG product is found in the event. + * @param[in] e The event to be processed. + * @param[in] corr_raw_timestamp The corrected raw timestamp from the artdaq::RawEventHeader product. + * @param[in,out] timestamp The closest ETRIG timestamp to the raw timestamp (if found). + * @return A boolean indicating if a valid ETRIG timestamp was found close enough to the raw timestamp. + * @details It searches for the SPEC-TDC products in the event and looks for the ETRIG timestamps. If any ETRIG + * timestamp is found, it checks which one is the closest to the raw timestamp and if it is close enough (i.e. + * within fraw_trig_max_diff) it returns it as output. + */ bool sbndaq::SBNDXARAPUCADecoder::get_spec_tdc_etrig_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t& timestamp) { bool ett_found = false; @@ -718,7 +718,7 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto } if (fverbose | fdebug_timing) { - std::cout << std::fixed << std::setprecision(3) << std::endl; + std::cout << std::fixed << std::setprecision(3); if (factive_timing_frame == SPEC_TDC_TIMING) { std::cout << " > SBNDXARAPUCADecoder::decode_fragment: SPEC-TDC time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; } else if (factive_timing_frame == PTB_TIMING) { @@ -726,6 +726,7 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto } else { // CAEN_ONLY_TIMING std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; } + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: TTT_end_ticks = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; } // =============== Start decoding the waveforms =============== // diff --git a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl index 3456450f9..774032157 100644 --- a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl +++ b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl @@ -32,16 +32,16 @@ xarapucadecoder: # - Output data product instance name. waveforms_instance_name: "XARAPUCAChannels" # Name for the instance product containing the raw decoded waveforms. timing_ref_instance_name: "" # Name for the instance product containing the timing reference information. - store_debug_waveforms: 0 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). + store_debug_waveforms: -1 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). # - Debug options. debug_tdc_handle: false # (De)activates SPEC-TDC art::Handle information printing. debug_ptb_handle: false # (De)activates PTB art::Handle information printing. - debug_fragments_handle: false # (De)activates V1740B CAEN fragments art::Handle information printing. - debug_timing: false # (De)activates timing data printing. + debug_fragments_handle: true # (De)activates V1740B CAEN fragments art::Handle information printing. + debug_timing: true # (De)activates timing data printing. debug_buffer: false # (De)activates buffer status printing. debug_waveforms: false # (De)activates waveforms decoding printing. # - Verbose option. - verbose: false # (De)activates verbosity. + verbose: true # (De)activates verbosity. } END_PROLOG \ No newline at end of file From 1e492fdc7c9745bb4264427560fa3a798d2fe9d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Thu, 9 Oct 2025 05:33:50 -0500 Subject: [PATCH 02/75] Shift timing function --- .../XARAPUCA/SBNDXARAPUCADecoder_module.cc | 214 ++++++++++++------ 1 file changed, 147 insertions(+), 67 deletions(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index 5be0a9e5d..655c26cfb 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -137,6 +137,7 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { bool get_ptb_hlt_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t & timestamp, uint16_t & hlt_code); bool get_spec_tdc_etrig_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t & timestamp); + void shift_time(const artdaq::Fragment& fragment, uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp); void save_prod_wvfm(size_t board_idx, size_t ch, double ini_wvfm_timestamp, const std::vector > & wvfms, std::vector & prod_wvfms); void save_debug_wvfm(size_t board_idx, size_t fragment_idx, int ch, double ini_wvfm_timestamp, double end_wvfm_timestamp, const std::vector > & wvfms); @@ -616,6 +617,10 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto if (valid_fragment) { if (fverbose) std::cout << "\n > SBNDXARAPUCADecoder::decode_fragment: decoding V1740 CAEN fragment " << fragment_indices[board_idx] << " from the board " << board_idx << " (slot " << fboard_id_list[board_idx] << "):" << std::endl; + //bool is_nominal_length = false; + //bool is_within_nominal_length = false; + //bool is_first = false; + // =============== Accesses Event metadata and Event header for this fragment =============== // CAENV1740Fragment caen_fragment(fragment); @@ -659,76 +664,81 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto // =============== Extracts timing information for this fragment =============== // // Gets the timing information of the CAEN fragment. - int64_t pulse_duration_ns = num_samples_per_wvfm * fns_per_sample; // ns. - uint64_t frag_timestamp = fragment.timestamp(); // ns. - int64_t frag_timestamp_s = frag_timestamp / NANOSEC_IN_SEC; // s. - int64_t frag_timestamp_ns = frag_timestamp % NANOSEC_IN_SEC; // ns. +// int64_t pulse_duration_ns = num_samples_per_wvfm * fns_per_sample; // ns. +// uint64_t frag_timestamp = fragment.timestamp(); // ns. +// int64_t frag_timestamp_s = frag_timestamp / NANOSEC_IN_SEC; // s. +// int64_t frag_timestamp_ns = frag_timestamp % NANOSEC_IN_SEC; // ns. uint32_t TTT_ticks = header.triggerTime(); int64_t TTT_end_ns = TTT_ticks * NANOSEC_PER_TICK; // ns. - // Gets the full TTT timestamp. - uint64_t full_TTT = 0; - // If the fragment timestamp is greater than the TTT end timestamp, it means that rollover occurred. - if (frag_timestamp_ns > TTT_end_ns) { - if (fverbose | fdebug_timing) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN TTT rollover occurred w.r.t. the fragment timestamp (FTS)." << std::endl; - full_TTT = (frag_timestamp_s + 1) * NANOSEC_IN_SEC + TTT_end_ns; - } else { - full_TTT = frag_timestamp_s * NANOSEC_IN_SEC + TTT_end_ns; - } - - int64_t ref_timestamp = 0; - - double ini_wvfm_timestamp = 0; - double end_wvfm_timestamp = 0; - - // If an ETRIG or HLT timestamp was found it restarts the time from it. Otherwise the CAEN time frame is assigned. - if (factive_timing_frame != CAEN_ONLY_TIMING) { - ref_timestamp = signed_difference(full_TTT, timestamp); // ns. - - ini_wvfm_timestamp = (ref_timestamp - pulse_duration_ns) * NANOSEC_TO_MICROSEC; // us. - end_wvfm_timestamp = ref_timestamp * NANOSEC_TO_MICROSEC; // us. - } else { - ref_timestamp = full_TTT; // ns. - - ini_wvfm_timestamp = ((ref_timestamp - pulse_duration_ns) % NANOSEC_IN_SEC) * NANOSEC_TO_MICROSEC; // ns. - end_wvfm_timestamp = (ref_timestamp % NANOSEC_IN_SEC) * NANOSEC_TO_MICROSEC; // us. - } - if (fdebug_timing) { - std::cout << std::fixed << std::setprecision(0); - std::cout << "\t\t ns/tick = " << NANOSEC_PER_TICK << ", ns/sample = " << fns_per_sample << std::endl; - std::cout << "\t\t TTT header.TriggerTime() [TTT_ticks] = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; std::cout << "\t\t TTT header.extendedTriggerTime() [TTT_ticks] = " << header.extendedTriggerTime() << " ticks. \t TTT_end_ns = " << print_timestamp(header.extendedTriggerTime() * NANOSEC_PER_TICK) << "." << std::endl; std::cout << "\t\t TTT header.triggerTimeRollOver(): " << header.triggerTimeRollOver() << std::endl; - std::cout << "\t\t Full Fragment timestamp: " << print_timestamp(frag_timestamp) << " = " << frag_timestamp_s << " s " << frag_timestamp_ns << " ns." << std::endl; - std::cout << "\t\t Full TTT - fragment timestamp = "<< abs_difference(full_TTT, frag_timestamp) << " ns." << " Post-percent: " << (double(abs_difference(full_TTT, frag_timestamp)) / double(pulse_duration_ns)) * 100 << "%." << std::endl; - if (factive_timing_frame == SPEC_TDC_TIMING) { - std::cout << "\t ETRIG (SPEC-TDC) timestamp of the fragment: " << std::endl; - std::cout << "\t\t Full UTC ETRIG timestamp: " << print_timestamp(timestamp) << "." << std::endl; - std::cout << "\t\t ETRIG SPEC-TDC difference applied to the CAEN frame (full timestamps): " << print_timestamp(full_TTT) << " - " << print_timestamp(timestamp) << " = " << ref_timestamp << " ns." << std::endl; - } else if (factive_timing_frame == PTB_TIMING) { - std::cout << "\t HLT ETRIG (PTB) timestamp of the fragment: " << std::endl; - std::cout << "\t\t Full UTC HLT ETRIG timestamp: " << print_timestamp(timestamp) << "." << std::endl; - std::cout << "\t\t HLT ETRIG (PTB) difference applied to the CAEN frame (full timestamps): " << print_timestamp(full_TTT) << " - " << print_timestamp(timestamp) << " = " << ref_timestamp << " ns." << std::endl; - } else if (factive_timing_frame == CAEN_ONLY_TIMING) { - std::cout << "\t CAEN trigger timestamp (TTT) of the fragment: " << std::endl; - std::cout << "\t\t Full UTC TTT timestamp: " << print_timestamp(full_TTT) << " = " << full_TTT / NANOSEC_IN_SEC << " s " << TTT_end_ns << " ns." << std::endl; - } - } - - if (fverbose | fdebug_timing) { - std::cout << std::fixed << std::setprecision(3); - if (factive_timing_frame == SPEC_TDC_TIMING) { - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: SPEC-TDC time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; - } else if (factive_timing_frame == PTB_TIMING) { - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: PTB time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; - } else { // CAEN_ONLY_TIMING - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; - } - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: TTT_end_ticks = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; } - +// +// // Gets the full TTT timestamp. +// uint64_t full_TTT = 0; +// // If the fragment timestamp is greater than the TTT end timestamp, it means that rollover occurred. +// if (frag_timestamp_ns > TTT_end_ns) { +// if (fverbose | fdebug_timing) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN TTT rollover occurred w.r.t. the fragment timestamp (FTS)." << std::endl; +// full_TTT = (frag_timestamp_s + 1) * NANOSEC_IN_SEC + TTT_end_ns; +// } else { +// full_TTT = frag_timestamp_s * NANOSEC_IN_SEC + TTT_end_ns; +// } +// +// int64_t ref_timestamp = 0; +// +// double ini_wvfm_timestamp = 0; +// double end_wvfm_timestamp = 0; +// +// // If an ETRIG or HLT timestamp was found it restarts the time from it. Otherwise the CAEN time frame is assigned. +// if (factive_timing_frame != CAEN_ONLY_TIMING) { +// ref_timestamp = signed_difference(full_TTT, timestamp); // ns. +// +// ini_wvfm_timestamp = (ref_timestamp - pulse_duration_ns) * NANOSEC_TO_MICROSEC; // us. +// end_wvfm_timestamp = ref_timestamp * NANOSEC_TO_MICROSEC; // us. +// } else { +// ref_timestamp = full_TTT; // ns. +// +// ini_wvfm_timestamp = ((ref_timestamp - pulse_duration_ns) % NANOSEC_IN_SEC) * NANOSEC_TO_MICROSEC; // ns. +// end_wvfm_timestamp = (ref_timestamp % NANOSEC_IN_SEC) * NANOSEC_TO_MICROSEC; // us. +// } +// +// if (fdebug_timing) { +// std::cout << std::fixed << std::setprecision(0); +// std::cout << "\t\t ns/tick = " << NANOSEC_PER_TICK << ", ns/sample = " << fns_per_sample << std::endl; +// std::cout << "\t\t TTT header.TriggerTime() [TTT_ticks] = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; +// std::cout << "\t\t TTT header.extendedTriggerTime() [TTT_ticks] = " << header.extendedTriggerTime() << " ticks. \t TTT_end_ns = " << print_timestamp(header.extendedTriggerTime() * NANOSEC_PER_TICK) << "." << std::endl; +// std::cout << "\t\t TTT header.triggerTimeRollOver(): " << header.triggerTimeRollOver() << std::endl; +// std::cout << "\t\t Full Fragment timestamp: " << print_timestamp(frag_timestamp) << " = " << frag_timestamp_s << " s " << frag_timestamp_ns << " ns." << std::endl; +// std::cout << "\t\t Full TTT - fragment timestamp = "<< abs_difference(full_TTT, frag_timestamp) << " ns." << " Post-percent: " << (double(abs_difference(full_TTT, frag_timestamp)) / double(pulse_duration_ns)) * 100 << "%." << std::endl; +// if (factive_timing_frame == SPEC_TDC_TIMING) { +// std::cout << "\t ETRIG (SPEC-TDC) timestamp of the fragment: " << std::endl; +// std::cout << "\t\t Full UTC ETRIG timestamp: " << print_timestamp(timestamp) << "." << std::endl; +// std::cout << "\t\t ETRIG SPEC-TDC difference applied to the CAEN frame (full timestamps): " << print_timestamp(full_TTT) << " - " << print_timestamp(timestamp) << " = " << ref_timestamp << " ns." << std::endl; +// } else if (factive_timing_frame == PTB_TIMING) { +// std::cout << "\t HLT ETRIG (PTB) timestamp of the fragment: " << std::endl; +// std::cout << "\t\t Full UTC HLT ETRIG timestamp: " << print_timestamp(timestamp) << "." << std::endl; +// std::cout << "\t\t HLT ETRIG (PTB) difference applied to the CAEN frame (full timestamps): " << print_timestamp(full_TTT) << " - " << print_timestamp(timestamp) << " = " << ref_timestamp << " ns." << std::endl; +// } else if (factive_timing_frame == CAEN_ONLY_TIMING) { +// std::cout << "\t CAEN trigger timestamp (TTT) of the fragment: " << std::endl; +// std::cout << "\t\t Full UTC TTT timestamp: " << print_timestamp(full_TTT) << " = " << full_TTT / NANOSEC_IN_SEC << " s " << TTT_end_ns << " ns." << std::endl; +// } +// } +// +// if (fverbose | fdebug_timing) { +// std::cout << std::fixed << std::setprecision(3); +// if (factive_timing_frame == SPEC_TDC_TIMING) { +// std::cout << " > SBNDXARAPUCADecoder::decode_fragment: SPEC-TDC time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; +// } else if (factive_timing_frame == PTB_TIMING) { +// std::cout << " > SBNDXARAPUCADecoder::decode_fragment: PTB time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; +// } else { // CAEN_ONLY_TIMING +// std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; +// } +// std::cout << " > SBNDXARAPUCADecoder::decode_fragment: TTT_end_ticks = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; +// } +// // =============== Start decoding the waveforms =============== // if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding of the waveforms starting... " << std::endl; @@ -771,6 +781,11 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto S++; } } + + + double ini_wvfm_timestamp = 0; + double end_wvfm_timestamp = 0; + shift_time(fragment, TTT_ticks, TTT_end_ns, timestamp, num_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); // The decoded waveforms are dumped into two products: // - A xarapucadecoder-art.root file with the OpDetWaveforms as the product of this producer for further analysis. @@ -878,6 +893,71 @@ void sbndaq::SBNDXARAPUCADecoder::save_debug_wvfm(size_t board_idx, size_t fragm } +void sbndaq::SBNDXARAPUCADecoder::shift_time(const artdaq::Fragment& fragment, uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp) { + + int64_t pulse_duration_ns = num_samples_per_wvfm * fns_per_sample; // ns. + uint64_t frag_timestamp = fragment.timestamp(); // ns. + int64_t frag_timestamp_s = frag_timestamp / NANOSEC_IN_SEC; // s. + int64_t frag_timestamp_ns = frag_timestamp % NANOSEC_IN_SEC; // ns. + + // Gets the full TTT timestamp. + uint64_t full_TTT = 0; + // If the fragment timestamp is greater than the TTT end timestamp, it means that rollover occurred. + if (frag_timestamp_ns > TTT_end_ns) { + if (fverbose | fdebug_timing) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN TTT rollover occurred w.r.t. the fragment timestamp (FTS)." << std::endl; + full_TTT = (frag_timestamp_s + 1) * NANOSEC_IN_SEC + TTT_end_ns; + } else { + full_TTT = frag_timestamp_s * NANOSEC_IN_SEC + TTT_end_ns; + } + + int64_t ref_timestamp = 0; + + // If an ETRIG or HLT timestamp was found it restarts the time from it. Otherwise the CAEN time frame is assigned. + if (factive_timing_frame != CAEN_ONLY_TIMING) { + ref_timestamp = signed_difference(full_TTT, timestamp); // ns. + + ini_wvfm_timestamp = (ref_timestamp - pulse_duration_ns) * NANOSEC_TO_MICROSEC; // us. + end_wvfm_timestamp = ref_timestamp * NANOSEC_TO_MICROSEC; // us. + } else { + ref_timestamp = full_TTT; // ns. + + ini_wvfm_timestamp = ((ref_timestamp - pulse_duration_ns) % NANOSEC_IN_SEC) * NANOSEC_TO_MICROSEC; // ns. + end_wvfm_timestamp = (ref_timestamp % NANOSEC_IN_SEC) * NANOSEC_TO_MICROSEC; // us. + } + + if (fdebug_timing) { + std::cout << std::fixed << std::setprecision(0); + std::cout << "\t\t ns/tick = " << NANOSEC_PER_TICK << ", ns/sample = " << fns_per_sample << std::endl; + std::cout << "\t\t TTT header.TriggerTime() [TTT_ticks] = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; + std::cout << "\t\t Full Fragment timestamp: " << print_timestamp(frag_timestamp) << " = " << frag_timestamp_s << " s " << frag_timestamp_ns << " ns." << std::endl; + std::cout << "\t\t Full TTT - fragment timestamp = "<< abs_difference(full_TTT, frag_timestamp) << " ns." << " Post-percent: " << (double(abs_difference(full_TTT, frag_timestamp)) / double(pulse_duration_ns)) * 100 << "%." << std::endl; + if (factive_timing_frame == SPEC_TDC_TIMING) { + std::cout << "\t ETRIG (SPEC-TDC) timestamp of the fragment: " << std::endl; + std::cout << "\t\t Full UTC ETRIG timestamp: " << print_timestamp(timestamp) << "." << std::endl; + std::cout << "\t\t ETRIG SPEC-TDC difference applied to the CAEN frame (full timestamps): " << print_timestamp(full_TTT) << " - " << print_timestamp(timestamp) << " = " << ref_timestamp << " ns." << std::endl; + } else if (factive_timing_frame == PTB_TIMING) { + std::cout << "\t HLT ETRIG (PTB) timestamp of the fragment: " << std::endl; + std::cout << "\t\t Full UTC HLT ETRIG timestamp: " << print_timestamp(timestamp) << "." << std::endl; + std::cout << "\t\t HLT ETRIG (PTB) difference applied to the CAEN frame (full timestamps): " << print_timestamp(full_TTT) << " - " << print_timestamp(timestamp) << " = " << ref_timestamp << " ns." << std::endl; + } else if (factive_timing_frame == CAEN_ONLY_TIMING) { + std::cout << "\t CAEN trigger timestamp (TTT) of the fragment: " << std::endl; + std::cout << "\t\t Full UTC TTT timestamp: " << print_timestamp(full_TTT) << " = " << full_TTT / NANOSEC_IN_SEC << " s " << TTT_end_ns << " ns." << std::endl; + } + } + + if (fverbose | fdebug_timing) { + std::cout << std::fixed << std::setprecision(3); + if (factive_timing_frame == SPEC_TDC_TIMING) { + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: SPEC-TDC time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; + } else if (factive_timing_frame == PTB_TIMING) { + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: PTB time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; + } else { // CAEN_ONLY_TIMING + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; + } + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: TTT_end_ticks = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; + } +} + /** * @brief Extract a sample from a 64-bit buffer using the specified bit positions. * @@ -975,11 +1055,11 @@ uint64_t sbndaq::SBNDXARAPUCADecoder::abs_difference(uint64_t t1, uint64_t t2) { } /** -* @brief Formats a timestamp in nanoseconds into a easily readable string format. -* @param[in] timestamp The timestamp in nanoseconds to be formatted. -* @return A string representation of the timestamp in the format "(seconds)nanoseconds ns". -* @details The function divides the input timestamp by 1,000,000,000 to obtain the seconds component and uses the modulus operator to get the remaining nanoseconds. -*/ + * @brief Formats a timestamp in nanoseconds into a easily readable string format. + * @param[in] timestamp The timestamp in nanoseconds to be formatted. + * @return A string representation of the timestamp in the format "(seconds)nanoseconds ns". + * @details The function divides the input timestamp by 1,000,000,000 to obtain the seconds component and uses the modulus operator to get the remaining nanoseconds. + */ std::string sbndaq::SBNDXARAPUCADecoder::print_timestamp(uint64_t timestamp) { return "(" + std::to_string(timestamp / NANOSEC_IN_SEC) + ")" + std::to_string(timestamp % NANOSEC_IN_SEC) + " ns"; } From 3f93cebdce39d9be4f21d180cc9fdcf3d5a576dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Thu, 9 Oct 2025 06:07:47 -0500 Subject: [PATCH 03/75] Waveforms decoding function --- .../XARAPUCA/SBNDXARAPUCADecoder_module.cc | 195 ++++++++---------- .../Decoders/XARAPUCA/xarapucadecoder.fcl | 2 +- 2 files changed, 89 insertions(+), 108 deletions(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index 655c26cfb..72020207c 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -138,6 +138,7 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { bool get_ptb_hlt_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t & timestamp, uint16_t & hlt_code); bool get_spec_tdc_etrig_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t & timestamp); void shift_time(const artdaq::Fragment& fragment, uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp); + void decode_waveforms(const artdaq::Fragment& fragment, std::vector>& wvfms, size_t header_size, uint32_t num_channels, uint32_t num_samples_per_wvfm, uint32_t num_words_per_wvfms, uint32_t num_samples_per_group); void save_prod_wvfm(size_t board_idx, size_t ch, double ini_wvfm_timestamp, const std::vector > & wvfms, std::vector & prod_wvfms); void save_debug_wvfm(size_t board_idx, size_t fragment_idx, int ch, double ini_wvfm_timestamp, double end_wvfm_timestamp, const std::vector > & wvfms); @@ -634,7 +635,8 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto // Gets the number of words of the header and the waveforms. uint32_t num_words_per_event = header.eventSize; - uint32_t num_words_per_header = sizeof(CAENV1740EventHeader) / sizeof(uint32_t); + size_t header_size = sizeof(CAENV1740EventHeader); + uint32_t num_words_per_header = header_size / sizeof(uint32_t); uint32_t num_words_per_wvfms = (num_words_per_event - num_words_per_header); uint32_t num_bits_per_all_wvfms = num_words_per_wvfms * BITS_PER_WORD; @@ -663,12 +665,6 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto // =============== Extracts timing information for this fragment =============== // - // Gets the timing information of the CAEN fragment. -// int64_t pulse_duration_ns = num_samples_per_wvfm * fns_per_sample; // ns. -// uint64_t frag_timestamp = fragment.timestamp(); // ns. -// int64_t frag_timestamp_s = frag_timestamp / NANOSEC_IN_SEC; // s. -// int64_t frag_timestamp_ns = frag_timestamp % NANOSEC_IN_SEC; // ns. - uint32_t TTT_ticks = header.triggerTime(); int64_t TTT_end_ns = TTT_ticks * NANOSEC_PER_TICK; // ns. @@ -676,113 +672,53 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto std::cout << "\t\t TTT header.extendedTriggerTime() [TTT_ticks] = " << header.extendedTriggerTime() << " ticks. \t TTT_end_ns = " << print_timestamp(header.extendedTriggerTime() * NANOSEC_PER_TICK) << "." << std::endl; std::cout << "\t\t TTT header.triggerTimeRollOver(): " << header.triggerTimeRollOver() << std::endl; } + +// // =============== Start decoding the waveforms =============== // + std::vector > wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); + decode_waveforms(fragment, wvfms, header_size, num_channels, num_samples_per_wvfm, num_words_per_wvfms, num_samples_per_group); +// if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding of the waveforms starting... " << std::endl; +// +// std::vector > wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); // -// // Gets the full TTT timestamp. -// uint64_t full_TTT = 0; -// // If the fragment timestamp is greater than the TTT end timestamp, it means that rollover occurred. -// if (frag_timestamp_ns > TTT_end_ns) { -// if (fverbose | fdebug_timing) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN TTT rollover occurred w.r.t. the fragment timestamp (FTS)." << std::endl; -// full_TTT = (frag_timestamp_s + 1) * NANOSEC_IN_SEC + TTT_end_ns; -// } else { -// full_TTT = frag_timestamp_s * NANOSEC_IN_SEC + TTT_end_ns; -// } -// -// int64_t ref_timestamp = 0; -// -// double ini_wvfm_timestamp = 0; -// double end_wvfm_timestamp = 0; -// -// // If an ETRIG or HLT timestamp was found it restarts the time from it. Otherwise the CAEN time frame is assigned. -// if (factive_timing_frame != CAEN_ONLY_TIMING) { -// ref_timestamp = signed_difference(full_TTT, timestamp); // ns. -// -// ini_wvfm_timestamp = (ref_timestamp - pulse_duration_ns) * NANOSEC_TO_MICROSEC; // us. -// end_wvfm_timestamp = ref_timestamp * NANOSEC_TO_MICROSEC; // us. -// } else { -// ref_timestamp = full_TTT; // ns. +// // Absolute sample number [0, TOTAL_NUM_SAMPLES] where TOTAL_NUM_SAMPLES is the total number of samples stored for an event. +// uint32_t S = 0; +// // Buffer variables. +// uint64_t buffer = 0; +// uint32_t bits_in_buffer = 0; // -// ini_wvfm_timestamp = ((ref_timestamp - pulse_duration_ns) % NANOSEC_IN_SEC) * NANOSEC_TO_MICROSEC; // ns. -// end_wvfm_timestamp = (ref_timestamp % NANOSEC_IN_SEC) * NANOSEC_TO_MICROSEC; // us. -// } +// // Data pointer to the beggining of the waveforms stores in the event. +// const uint32_t* data_ptr = reinterpret_cast(fragment.dataBeginBytes() + sizeof(CAENV1740EventHeader)); +// // Accesses each word, stores it in the buffer and then the samples are extracted from the buffer. +// for (size_t j = 0; j < num_words_per_wvfms; j++) { +// uint64_t word = read_word(data_ptr); // -// if (fdebug_timing) { -// std::cout << std::fixed << std::setprecision(0); -// std::cout << "\t\t ns/tick = " << NANOSEC_PER_TICK << ", ns/sample = " << fns_per_sample << std::endl; -// std::cout << "\t\t TTT header.TriggerTime() [TTT_ticks] = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; -// std::cout << "\t\t TTT header.extendedTriggerTime() [TTT_ticks] = " << header.extendedTriggerTime() << " ticks. \t TTT_end_ns = " << print_timestamp(header.extendedTriggerTime() * NANOSEC_PER_TICK) << "." << std::endl; -// std::cout << "\t\t TTT header.triggerTimeRollOver(): " << header.triggerTimeRollOver() << std::endl; -// std::cout << "\t\t Full Fragment timestamp: " << print_timestamp(frag_timestamp) << " = " << frag_timestamp_s << " s " << frag_timestamp_ns << " ns." << std::endl; -// std::cout << "\t\t Full TTT - fragment timestamp = "<< abs_difference(full_TTT, frag_timestamp) << " ns." << " Post-percent: " << (double(abs_difference(full_TTT, frag_timestamp)) / double(pulse_duration_ns)) * 100 << "%." << std::endl; -// if (factive_timing_frame == SPEC_TDC_TIMING) { -// std::cout << "\t ETRIG (SPEC-TDC) timestamp of the fragment: " << std::endl; -// std::cout << "\t\t Full UTC ETRIG timestamp: " << print_timestamp(timestamp) << "." << std::endl; -// std::cout << "\t\t ETRIG SPEC-TDC difference applied to the CAEN frame (full timestamps): " << print_timestamp(full_TTT) << " - " << print_timestamp(timestamp) << " = " << ref_timestamp << " ns." << std::endl; -// } else if (factive_timing_frame == PTB_TIMING) { -// std::cout << "\t HLT ETRIG (PTB) timestamp of the fragment: " << std::endl; -// std::cout << "\t\t Full UTC HLT ETRIG timestamp: " << print_timestamp(timestamp) << "." << std::endl; -// std::cout << "\t\t HLT ETRIG (PTB) difference applied to the CAEN frame (full timestamps): " << print_timestamp(full_TTT) << " - " << print_timestamp(timestamp) << " = " << ref_timestamp << " ns." << std::endl; -// } else if (factive_timing_frame == CAEN_ONLY_TIMING) { -// std::cout << "\t CAEN trigger timestamp (TTT) of the fragment: " << std::endl; -// std::cout << "\t\t Full UTC TTT timestamp: " << print_timestamp(full_TTT) << " = " << full_TTT / NANOSEC_IN_SEC << " s " << TTT_end_ns << " ns." << std::endl; -// } -// } +// // Adds the new word to the buffer and increments the number of bits stored in it. +// if (fdebug_buffer) std::cout << buffer << "[word: " << word << "]" << std::endl; +// buffer |= word << bits_in_buffer; +// bits_in_buffer += BITS_PER_WORD; // bytes * 8 bits/byte +// if (fdebug_buffer) std::cout << " +" << buffer << " [bits in buffer: "<< bits_in_buffer << "]" << std::endl; // -// if (fverbose | fdebug_timing) { -// std::cout << std::fixed << std::setprecision(3); -// if (factive_timing_frame == SPEC_TDC_TIMING) { -// std::cout << " > SBNDXARAPUCADecoder::decode_fragment: SPEC-TDC time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; -// } else if (factive_timing_frame == PTB_TIMING) { -// std::cout << " > SBNDXARAPUCADecoder::decode_fragment: PTB time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; -// } else { // CAEN_ONLY_TIMING -// std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; +// // Obtains 12-bit sequences from the buffer and assigns each sample to the channel and channel sample it belongs to. +// while (bits_in_buffer >= BITS_PER_SAMPLE) { +// // Computes board channel, channel sample and group channel and assigns the sample to those indices. +// uint32_t g = (S / num_samples_per_group); // Group index. +// uint32_t c = ((S / NUM_CONSECUTIVE_SAMPLES) % NUM_CHANNELS_PER_GROUP) + g * NUM_GROUPS; // Channel index. +// uint32_t s = (S % NUM_CONSECUTIVE_SAMPLES) + ((S / NUM_SAMPLES_PER_ROUND) * NUM_CONSECUTIVE_SAMPLES) % num_samples_per_wvfm; // Sample/channel index. +// uint16_t sample = get_sample(buffer, BITS_PER_SAMPLE - 1, 0); +// wvfms[c][s] = sample; +// if (fdebug_waveforms) std::cout << "\tSample: " << sample << "\tg: " << g << "\tch: " << c << "\ts:" << s << "\tS: " << S << std::endl; +// +// // Updates the buffer status removing the read bits and decreasing the number of bits stored in it. +// buffer >>= BITS_PER_SAMPLE; +// bits_in_buffer -= BITS_PER_SAMPLE; +// if (fdebug_buffer) std::cout << " -" << buffer << " [bits in buffer: "<< bits_in_buffer << "]" << std::endl; +// +// // Increments the absolute sample step. +// S++; // } -// std::cout << " > SBNDXARAPUCADecoder::decode_fragment: TTT_end_ticks = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; // } -// - // =============== Start decoding the waveforms =============== // - if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding of the waveforms starting... " << std::endl; - - std::vector > wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); - - // Absolute sample number [0, TOTAL_NUM_SAMPLES] where TOTAL_NUM_SAMPLES is the total number of samples stored for an event. - uint32_t S = 0; - // Buffer variables. - uint64_t buffer = 0; - uint32_t bits_in_buffer = 0; - - // Data pointer to the beggining of the waveforms stores in the event. - const uint32_t* data_ptr = reinterpret_cast(fragment.dataBeginBytes() + sizeof(CAENV1740EventHeader)); - // Accesses each word, stores it in the buffer and then the samples are extracted from the buffer. - for (size_t j = 0; j < num_words_per_wvfms; j++) { - uint64_t word = read_word(data_ptr); - - // Adds the new word to the buffer and increments the number of bits stored in it. - if (fdebug_buffer) std::cout << buffer << "[word: " << word << "]" << std::endl; - buffer |= word << bits_in_buffer; - bits_in_buffer += BITS_PER_WORD; // bytes * 8 bits/byte - if (fdebug_buffer) std::cout << " +" << buffer << " [bits in buffer: "<< bits_in_buffer << "]" << std::endl; - - // Obtains 12-bit sequences from the buffer and assigns each sample to the channel and channel sample it belongs to. - while (bits_in_buffer >= BITS_PER_SAMPLE) { - // Computes board channel, channel sample and group channel and assigns the sample to those indices. - uint32_t g = (S / num_samples_per_group); // Group index. - uint32_t c = ((S / NUM_CONSECUTIVE_SAMPLES) % NUM_CHANNELS_PER_GROUP) + g * NUM_GROUPS; // Channel index. - uint32_t s = (S % NUM_CONSECUTIVE_SAMPLES) + ((S / NUM_SAMPLES_PER_ROUND) * NUM_CONSECUTIVE_SAMPLES) % num_samples_per_wvfm; // Sample/channel index. - uint16_t sample = get_sample(buffer, BITS_PER_SAMPLE - 1, 0); - wvfms[c][s] = sample; - if (fdebug_waveforms) std::cout << "\tSample: " << sample << "\tg: " << g << "\tch: " << c << "\ts:" << s << "\tS: " << S << std::endl; - - // Updates the buffer status removing the read bits and decreasing the number of bits stored in it. - buffer >>= BITS_PER_SAMPLE; - bits_in_buffer -= BITS_PER_SAMPLE; - if (fdebug_buffer) std::cout << " -" << buffer << " [bits in buffer: "<< bits_in_buffer << "]" << std::endl; - - // Increments the absolute sample step. - S++; - } - } - + // =============== Shifts timing to the selected timing reference frame =============== // double ini_wvfm_timestamp = 0; double end_wvfm_timestamp = 0; shift_time(fragment, TTT_ticks, TTT_end_ns, timestamp, num_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); @@ -958,6 +894,51 @@ void sbndaq::SBNDXARAPUCADecoder::shift_time(const artdaq::Fragment& fragment, u } } +void sbndaq::SBNDXARAPUCADecoder::decode_waveforms(const artdaq::Fragment& fragment, std::vector>& wvfms, size_t header_size, uint32_t num_channels, uint32_t num_samples_per_wvfm, uint32_t num_words_per_wvfms, uint32_t num_samples_per_group) { + // =============== Start decoding the waveforms =============== // + if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding of the waveforms starting... " << std::endl; + + //std::vector > wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); + + // Absolute sample number [0, TOTAL_NUM_SAMPLES] where TOTAL_NUM_SAMPLES is the total number of samples stored for an event. + uint32_t S = 0; + // Buffer variables. + uint64_t buffer = 0; + uint32_t bits_in_buffer = 0; + + // Data pointer to the beggining of the waveforms stores in the event. + const uint32_t* data_ptr = reinterpret_cast(fragment.dataBeginBytes() + header_size); + // Accesses each word, stores it in the buffer and then the samples are extracted from the buffer. + for (size_t j = 0; j < num_words_per_wvfms; j++) { + uint64_t word = read_word(data_ptr); + + // Adds the new word to the buffer and increments the number of bits stored in it. + if (fdebug_buffer) std::cout << buffer << "[word: " << word << "]" << std::endl; + buffer |= word << bits_in_buffer; + bits_in_buffer += BITS_PER_WORD; // bytes * 8 bits/byte + if (fdebug_buffer) std::cout << " +" << buffer << " [bits in buffer: "<< bits_in_buffer << "]" << std::endl; + + // Obtains 12-bit sequences from the buffer and assigns each sample to the channel and channel sample it belongs to. + while (bits_in_buffer >= BITS_PER_SAMPLE) { + // Computes board channel, channel sample and group channel and assigns the sample to those indices. + uint32_t g = (S / num_samples_per_group); // Group index. + uint32_t c = ((S / NUM_CONSECUTIVE_SAMPLES) % NUM_CHANNELS_PER_GROUP) + g * NUM_GROUPS; // Channel index. + uint32_t s = (S % NUM_CONSECUTIVE_SAMPLES) + ((S / NUM_SAMPLES_PER_ROUND) * NUM_CONSECUTIVE_SAMPLES) % num_samples_per_wvfm; // Sample/channel index. + uint16_t sample = get_sample(buffer, BITS_PER_SAMPLE - 1, 0); + wvfms[c][s] = sample; + if (fdebug_waveforms) std::cout << "\tSample: " << sample << "\tg: " << g << "\tch: " << c << "\ts:" << s << "\tS: " << S << std::endl; + + // Updates the buffer status removing the read bits and decreasing the number of bits stored in it. + buffer >>= BITS_PER_SAMPLE; + bits_in_buffer -= BITS_PER_SAMPLE; + if (fdebug_buffer) std::cout << " -" << buffer << " [bits in buffer: "<< bits_in_buffer << "]" << std::endl; + + // Increments the absolute sample step. + S++; + } + } +} + /** * @brief Extract a sample from a 64-bit buffer using the specified bit positions. * diff --git a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl index 774032157..022a6888c 100644 --- a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl +++ b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl @@ -32,7 +32,7 @@ xarapucadecoder: # - Output data product instance name. waveforms_instance_name: "XARAPUCAChannels" # Name for the instance product containing the raw decoded waveforms. timing_ref_instance_name: "" # Name for the instance product containing the timing reference information. - store_debug_waveforms: -1 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). + store_debug_waveforms: 33 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). # - Debug options. debug_tdc_handle: false # (De)activates SPEC-TDC art::Handle information printing. debug_ptb_handle: false # (De)activates PTB art::Handle information printing. From b416a56d558710b69fd964fa9a1f67a07df790c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Thu, 9 Oct 2025 07:20:43 -0500 Subject: [PATCH 04/75] Add dump waveforms function --- .../XARAPUCA/SBNDXARAPUCADecoder_module.cc | 135 ++++++++---------- 1 file changed, 63 insertions(+), 72 deletions(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index 72020207c..0131a5e49 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -74,7 +74,6 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { void produce(art::Event& e) override; private: - constexpr static uint64_t NANOSEC_IN_SEC = 1'000'000'000; /**< Number of nanoseconds in one second. */ constexpr static uint64_t MICROSEC_IN_NANOSEC = 1'000; /**< Number of nanoseconds in one microsecond. */ constexpr static double NANOSEC_TO_MICROSEC = 1E-3; /**< Conversion factor from nanoseconds to microseconds. */ @@ -91,6 +90,7 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { constexpr static uint16_t PTB_TIMING = 1; /**< Timing reference frame: HLT (High Level Trigger) timestamp from the PTB (Penn Trigger Board). */ constexpr static uint16_t CAEN_ONLY_TIMING = 2; /**< Timing reference frame: CAEN-only. */ + constexpr static uint16_t TTT_DEFAULT = 0; /**< Default integer value for the nominal TTT. */ constexpr static uint16_t HLT_NOT_FOUND = 999; /**< Random value to indicate no HL trigger found. */ constexpr static uint16_t HLT_TOO_FAR = 1000; /**< Random value to indicate HL trigger found but too far from the raw timestamp. */ @@ -140,6 +140,7 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { void shift_time(const artdaq::Fragment& fragment, uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp); void decode_waveforms(const artdaq::Fragment& fragment, std::vector>& wvfms, size_t header_size, uint32_t num_channels, uint32_t num_samples_per_wvfm, uint32_t num_words_per_wvfms, uint32_t num_samples_per_group); + void dump_waveforms(std::vector & prod_wvfms, const std::vector>& wvfms, std::vector & fragment_indices, size_t board_index, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp); void save_prod_wvfm(size_t board_idx, size_t ch, double ini_wvfm_timestamp, const std::vector > & wvfms, std::vector & prod_wvfms); void save_debug_wvfm(size_t board_idx, size_t fragment_idx, int ch, double ini_wvfm_timestamp, double end_wvfm_timestamp, const std::vector > & wvfms); @@ -621,7 +622,8 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto //bool is_nominal_length = false; //bool is_within_nominal_length = false; //bool is_first = false; - + //int32_t nominal_TTT = TTT_DEFAULT; + // =============== Accesses Event metadata and Event header for this fragment =============== // CAENV1740Fragment caen_fragment(fragment); @@ -663,6 +665,8 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto std::cout << "\t Number of samples per group (this fragment): " << num_samples_per_group << std::endl; } + std::vector > wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); + // =============== Extracts timing information for this fragment =============== // uint32_t TTT_ticks = header.triggerTime(); @@ -673,81 +677,41 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto std::cout << "\t\t TTT header.triggerTimeRollOver(): " << header.triggerTimeRollOver() << std::endl; } -// // =============== Start decoding the waveforms =============== // - std::vector > wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); + // =============== Start decoding the waveforms =============== // + //std::vector > fragment_wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); decode_waveforms(fragment, wvfms, header_size, num_channels, num_samples_per_wvfm, num_words_per_wvfms, num_samples_per_group); -// if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding of the waveforms starting... " << std::endl; -// -// std::vector > wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); -// -// // Absolute sample number [0, TOTAL_NUM_SAMPLES] where TOTAL_NUM_SAMPLES is the total number of samples stored for an event. -// uint32_t S = 0; -// // Buffer variables. -// uint64_t buffer = 0; -// uint32_t bits_in_buffer = 0; -// -// // Data pointer to the beggining of the waveforms stores in the event. -// const uint32_t* data_ptr = reinterpret_cast(fragment.dataBeginBytes() + sizeof(CAENV1740EventHeader)); -// // Accesses each word, stores it in the buffer and then the samples are extracted from the buffer. -// for (size_t j = 0; j < num_words_per_wvfms; j++) { -// uint64_t word = read_word(data_ptr); -// -// // Adds the new word to the buffer and increments the number of bits stored in it. -// if (fdebug_buffer) std::cout << buffer << "[word: " << word << "]" << std::endl; -// buffer |= word << bits_in_buffer; -// bits_in_buffer += BITS_PER_WORD; // bytes * 8 bits/byte -// if (fdebug_buffer) std::cout << " +" << buffer << " [bits in buffer: "<< bits_in_buffer << "]" << std::endl; -// -// // Obtains 12-bit sequences from the buffer and assigns each sample to the channel and channel sample it belongs to. -// while (bits_in_buffer >= BITS_PER_SAMPLE) { -// // Computes board channel, channel sample and group channel and assigns the sample to those indices. -// uint32_t g = (S / num_samples_per_group); // Group index. -// uint32_t c = ((S / NUM_CONSECUTIVE_SAMPLES) % NUM_CHANNELS_PER_GROUP) + g * NUM_GROUPS; // Channel index. -// uint32_t s = (S % NUM_CONSECUTIVE_SAMPLES) + ((S / NUM_SAMPLES_PER_ROUND) * NUM_CONSECUTIVE_SAMPLES) % num_samples_per_wvfm; // Sample/channel index. -// uint16_t sample = get_sample(buffer, BITS_PER_SAMPLE - 1, 0); -// wvfms[c][s] = sample; -// if (fdebug_waveforms) std::cout << "\tSample: " << sample << "\tg: " << g << "\tch: " << c << "\ts:" << s << "\tS: " << S << std::endl; -// -// // Updates the buffer status removing the read bits and decreasing the number of bits stored in it. -// buffer >>= BITS_PER_SAMPLE; -// bits_in_buffer -= BITS_PER_SAMPLE; -// if (fdebug_buffer) std::cout << " -" << buffer << " [bits in buffer: "<< bits_in_buffer << "]" << std::endl; -// -// // Increments the absolute sample step. -// S++; -// } -// } // =============== Shifts timing to the selected timing reference frame =============== // double ini_wvfm_timestamp = 0; double end_wvfm_timestamp = 0; shift_time(fragment, TTT_ticks, TTT_end_ns, timestamp, num_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); - // The decoded waveforms are dumped into two products: - // - A xarapucadecoder-art.root file with the OpDetWaveforms as the product of this producer for further analysis. - // - A decoder_hist.root file gathering a waveform histograms. - if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding complete, dumping products..." << std::endl; - - uint32_t num_debug_wvfms; - - if (fstore_debug_waveforms == -1) { - num_debug_wvfms = num_channels; - } else { - num_debug_wvfms = std::min(num_channels, fstore_debug_waveforms); - } - - uint32_t ch; - - for (ch = 0; ch < num_debug_wvfms; ch++) { - save_prod_wvfm(board_idx, ch, ini_wvfm_timestamp, wvfms, prod_wvfms); - save_debug_wvfm(board_idx, fragment_indices[board_idx], ch, ini_wvfm_timestamp, end_wvfm_timestamp, wvfms); - } - - for (;ch < num_channels; ch++) { - save_prod_wvfm(board_idx, ch, ini_wvfm_timestamp, wvfms, prod_wvfms); - } - - fragment_indices[board_idx]++; + dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); + // // The decoded waveforms are dumped into two products: + // // - A xarapucadecoder-art.root file with the OpDetWaveforms as the product of this producer for further analysis. + // // - A decoder_hist.root file gathering a waveform histograms. + // if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding complete, dumping products..." << std::endl; + // + // uint32_t num_debug_wvfms; +// + // if (fstore_debug_waveforms == -1) { + // num_debug_wvfms = num_channels; + // } else { + // num_debug_wvfms = std::min(num_channels, fstore_debug_waveforms); + // } +// + // uint32_t ch; +// + // for (ch = 0; ch < num_debug_wvfms; ch++) { + // save_prod_wvfm(board_idx, ch, ini_wvfm_timestamp, wvfms, prod_wvfms); + // save_debug_wvfm(board_idx, fragment_indices[board_idx], ch, ini_wvfm_timestamp, end_wvfm_timestamp, wvfms); + // } +// + // for (;ch < num_channels; ch++) { + // save_prod_wvfm(board_idx, ch, ini_wvfm_timestamp, wvfms, prod_wvfms); + // } +// + // fragment_indices[board_idx]++; } } @@ -898,8 +862,6 @@ void sbndaq::SBNDXARAPUCADecoder::decode_waveforms(const artdaq::Fragment& fragm // =============== Start decoding the waveforms =============== // if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding of the waveforms starting... " << std::endl; - //std::vector > wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); - // Absolute sample number [0, TOTAL_NUM_SAMPLES] where TOTAL_NUM_SAMPLES is the total number of samples stored for an event. uint32_t S = 0; // Buffer variables. @@ -939,6 +901,35 @@ void sbndaq::SBNDXARAPUCADecoder::decode_waveforms(const artdaq::Fragment& fragm } } +void sbndaq::SBNDXARAPUCADecoder::dump_waveforms(std::vector & prod_wvfms, const std::vector>& wvfms, std::vector & fragment_indices, size_t board_idx, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp) { + + // The decoded waveforms are dumped into two products: + // - A xarapucadecoder-art.root file with the OpDetWaveforms as the product of this producer for further analysis. + // - A decoder_hist.root file gathering a waveform histograms. + if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding complete, dumping products..." << std::endl; + + uint32_t num_debug_wvfms; + + if (fstore_debug_waveforms == -1) { + num_debug_wvfms = num_channels; + } else { + num_debug_wvfms = std::min(num_channels, fstore_debug_waveforms); + } + + uint32_t ch; + + for (ch = 0; ch < num_debug_wvfms; ch++) { + save_prod_wvfm(board_idx, ch, ini_wvfm_timestamp, wvfms, prod_wvfms); + save_debug_wvfm(board_idx, fragment_indices[board_idx], ch, ini_wvfm_timestamp, end_wvfm_timestamp, wvfms); + } + + for (;ch < num_channels; ch++) { + save_prod_wvfm(board_idx, ch, ini_wvfm_timestamp, wvfms, prod_wvfms); + } + + fragment_indices[board_idx]++; +} + /** * @brief Extract a sample from a 64-bit buffer using the specified bit positions. * From 0d9f64460644030a1db0559000e96aaaabc1fdf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Fri, 10 Oct 2025 05:44:36 -0500 Subject: [PATCH 05/75] Combine waveforms and correctly differentiates nominal from extended --- .../XARAPUCA/SBNDXARAPUCADecoder_module.cc | 120 +++++++++++------- .../Decoders/XARAPUCA/xarapucadecoder.fcl | 2 +- 2 files changed, 72 insertions(+), 50 deletions(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index 0131a5e49..ff9b9c99f 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -133,17 +133,19 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { bool fverbose; /**< If `true` it increases verbosity of console output for detailed processing steps. */ // Class methods. - void decode_fragment(uint64_t timestamp, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms); + void decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms); bool get_ptb_hlt_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t & timestamp, uint16_t & hlt_code); bool get_spec_tdc_etrig_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t & timestamp); - void shift_time(const artdaq::Fragment& fragment, uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp); + void shift_time(uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t frag_timestamp, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp); void decode_waveforms(const artdaq::Fragment& fragment, std::vector>& wvfms, size_t header_size, uint32_t num_channels, uint32_t num_samples_per_wvfm, uint32_t num_words_per_wvfms, uint32_t num_samples_per_group); - void dump_waveforms(std::vector & prod_wvfms, const std::vector>& wvfms, std::vector & fragment_indices, size_t board_index, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp); + void dump_waveforms(std::vector & prod_wvfms, std::vector>& wvfms, std::vector & fragment_indices, size_t board_index, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp); void save_prod_wvfm(size_t board_idx, size_t ch, double ini_wvfm_timestamp, const std::vector > & wvfms, std::vector & prod_wvfms); void save_debug_wvfm(size_t board_idx, size_t fragment_idx, int ch, double ini_wvfm_timestamp, double end_wvfm_timestamp, const std::vector > & wvfms); + void combine_waveforms(std::vector>& wvfms, const std::vector>& fragment_wvfms, uint32_t num_channels); + uint16_t get_sample(uint64_t buffer, uint32_t msb, uint32_t lsb); uint32_t read_word(const uint32_t* & data_ptr); unsigned int get_channel_id(unsigned int board, unsigned int board_channel); @@ -304,6 +306,10 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) bool found_caen = false; std::vector fragment_indices(fnum_caen_boards, 0); + std::vector> wvfms; + std::cout << "wvfms_size: " << wvfms.size() << std::endl; + int32_t nominal_TTT = TTT_DEFAULT; + uint64_t nominal_frag_timestamp = TTT_DEFAULT; if (fverbose | fdebug_fragments_handle) std::cout << "\n > SBNDXARAPUCADecoder::produce: searching for V1740 fragments..." << std::endl; @@ -341,7 +347,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) for (size_t f = 0; f < num_caen_fragments; f++) { const artdaq::Fragment fragment = *container_fragment[f].get(); - decode_fragment(timestamp, fragment_indices, fragment, *prod_wvfms); + decode_fragment(timestamp, nominal_frag_timestamp, nominal_TTT, fragment_indices, fragment, *prod_wvfms, wvfms); } // End CAEN V1740 fragments loop. } } // End Container fragments loop. @@ -353,7 +359,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) // It searches for all CAEN V1740 fragments. for (size_t f = 0; f < frag_handle_size; f++) { const artdaq::Fragment fragment = fragment_handle->at(f); - decode_fragment(timestamp, fragment_indices, fragment, *prod_wvfms); + decode_fragment(timestamp, nominal_frag_timestamp, nominal_TTT, fragment_indices, fragment, *prod_wvfms, wvfms); } // End CAEN V1740 fragments loop. } } // End extracting CAEN V1740 fragments. @@ -599,7 +605,10 @@ bool sbndaq::SBNDXARAPUCADecoder::get_ptb_hlt_timestamp(art::Event& e, uint64_t * - Populates the output vector (`prod_wvfms`) with decoded waveforms and optionally generates debug waveforms output. * */ -void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms) { + +void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms) { + std::cout << "decode_wvfms_size: " << wvfms.size() << std::endl; + auto fragment_id = fragment.fragmentID() - ffragment_id_offset; auto it = std::find(fboard_id_list.begin(), fboard_id_list.end(), fragment_id); size_t board_idx; @@ -619,10 +628,13 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto if (valid_fragment) { if (fverbose) std::cout << "\n > SBNDXARAPUCADecoder::decode_fragment: decoding V1740 CAEN fragment " << fragment_indices[board_idx] << " from the board " << board_idx << " (slot " << fboard_id_list[board_idx] << "):" << std::endl; - //bool is_nominal_length = false; + bool is_nominal_length = false; //bool is_within_nominal_length = false; - //bool is_first = false; - //int32_t nominal_TTT = TTT_DEFAULT; + bool is_first = false; + + + double ini_wvfm_timestamp = 0; + double end_wvfm_timestamp = 0; // =============== Accesses Event metadata and Event header for this fragment =============== // @@ -646,14 +658,15 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto uint32_t num_remaining_bits = num_bits_per_all_wvfms % BITS_PER_SAMPLE; uint32_t num_samples_per_wvfm = num_samples_per_all_wvfms / num_channels; uint32_t num_samples_per_group = num_samples_per_wvfm * NUM_CHANNELS_PER_GROUP; + uint32_t num_nominal_samples_per_wvfm = metadata->nSamples; if (fverbose | fdebug_waveforms) { - if (metadata->nSamples == num_samples_per_wvfm) { + if (num_nominal_samples_per_wvfm == num_samples_per_wvfm) { std::cout << " > SBNDXARAPUCADecoder::decode_fragment: [NOMINAL FRAGMENT] " << num_samples_per_wvfm << " samples/waveform." << " (" << num_samples_per_group << " samples per group - 8 channels per group -)." << std::endl; } else { std::cout << " > SBNDXARAPUCADecoder::decode_fragment: [EXTENDED FRAGMENT] " << num_samples_per_wvfm << " samples/waveform." << " (" << num_samples_per_group << " samples per group - 8 channels per group -)." << std::endl; } - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: nominal number of samples per waveform: " << metadata->nSamples << "." << std::endl; + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: nominal number of samples per waveform: " << num_nominal_samples_per_wvfm << "." << std::endl; std::cout << " > SBNDXARAPUCADecoder::decode_fragment: number of words for this fragment: " << num_words_per_event << " (Header: " << num_words_per_header << ", Waveform: " << num_words_per_wvfms << ") words." << std::endl; } @@ -665,10 +678,11 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto std::cout << "\t Number of samples per group (this fragment): " << num_samples_per_group << std::endl; } - std::vector > wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); + //std::vector > wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); // =============== Extracts timing information for this fragment =============== // + uint64_t frag_timestamp = fragment.timestamp(); // ns. uint32_t TTT_ticks = header.triggerTime(); int64_t TTT_end_ns = TTT_ticks * NANOSEC_PER_TICK; // ns. @@ -677,41 +691,38 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, std::vecto std::cout << "\t\t TTT header.triggerTimeRollOver(): " << header.triggerTimeRollOver() << std::endl; } - // =============== Start decoding the waveforms =============== // - //std::vector > fragment_wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); - decode_waveforms(fragment, wvfms, header_size, num_channels, num_samples_per_wvfm, num_words_per_wvfms, num_samples_per_group); - - // =============== Shifts timing to the selected timing reference frame =============== // - double ini_wvfm_timestamp = 0; - double end_wvfm_timestamp = 0; - shift_time(fragment, TTT_ticks, TTT_end_ns, timestamp, num_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); - - dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); - // // The decoded waveforms are dumped into two products: - // // - A xarapucadecoder-art.root file with the OpDetWaveforms as the product of this producer for further analysis. - // // - A decoder_hist.root file gathering a waveform histograms. - // if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding complete, dumping products..." << std::endl; - // - // uint32_t num_debug_wvfms; -// - // if (fstore_debug_waveforms == -1) { - // num_debug_wvfms = num_channels; - // } else { - // num_debug_wvfms = std::min(num_channels, fstore_debug_waveforms); - // } -// - // uint32_t ch; + //// =============== Start decoding the waveforms =============== // + std::vector > fragment_wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); + decode_waveforms(fragment, fragment_wvfms, header_size, num_channels, num_samples_per_wvfm, num_words_per_wvfms, num_samples_per_group); // - // for (ch = 0; ch < num_debug_wvfms; ch++) { - // save_prod_wvfm(board_idx, ch, ini_wvfm_timestamp, wvfms, prod_wvfms); - // save_debug_wvfm(board_idx, fragment_indices[board_idx], ch, ini_wvfm_timestamp, end_wvfm_timestamp, wvfms); - // } + //// =============== Shifts timing to the selected timing reference frame =============== // // - // for (;ch < num_channels; ch++) { - // save_prod_wvfm(board_idx, ch, ini_wvfm_timestamp, wvfms, prod_wvfms); - // } -// - // fragment_indices[board_idx]++; + //shift_time(fragment, TTT_ticks, TTT_end_ns, timestamp, num_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); + //dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); + //combine_waveforms(wvfms, fragment_wvfms, num_channels); + + is_nominal_length = (num_nominal_samples_per_wvfm == num_samples_per_wvfm); + is_first = (fragment_indices[board_idx] == 0); + + if (is_nominal_length) { + if (!is_first) { + std::cout << " NOT FIRST NOMINAL fragment " << std::endl; + std::cout << " nominal_TTT: " << nominal_TTT << " TTT_end_ns: " << TTT_end_ns << std::endl; + std::cout << " nominal_frag_timestamp: " << nominal_frag_timestamp << " frag_timestamp : " << frag_timestamp << std::endl; + shift_time(TTT_ticks, nominal_TTT, nominal_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); + dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); + } else { + std::cout << " FIRST NOMINAL fragment " << std::endl; + } + combine_waveforms(wvfms, fragment_wvfms, num_channels); + nominal_TTT = TTT_end_ns; + nominal_frag_timestamp = frag_timestamp; + } else { + std::cout << " EXTENDED fragment " << std::endl; + combine_waveforms(wvfms, fragment_wvfms, num_channels); + } + + fragment_indices[board_idx]++; } } @@ -793,10 +804,9 @@ void sbndaq::SBNDXARAPUCADecoder::save_debug_wvfm(size_t board_idx, size_t fragm } -void sbndaq::SBNDXARAPUCADecoder::shift_time(const artdaq::Fragment& fragment, uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp) { +void sbndaq::SBNDXARAPUCADecoder::shift_time(uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t frag_timestamp, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp) { int64_t pulse_duration_ns = num_samples_per_wvfm * fns_per_sample; // ns. - uint64_t frag_timestamp = fragment.timestamp(); // ns. int64_t frag_timestamp_s = frag_timestamp / NANOSEC_IN_SEC; // s. int64_t frag_timestamp_ns = frag_timestamp % NANOSEC_IN_SEC; // ns. @@ -901,7 +911,7 @@ void sbndaq::SBNDXARAPUCADecoder::decode_waveforms(const artdaq::Fragment& fragm } } -void sbndaq::SBNDXARAPUCADecoder::dump_waveforms(std::vector & prod_wvfms, const std::vector>& wvfms, std::vector & fragment_indices, size_t board_idx, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp) { +void sbndaq::SBNDXARAPUCADecoder::dump_waveforms(std::vector & prod_wvfms, std::vector>& wvfms, std::vector & fragment_indices, size_t board_idx, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp) { // The decoded waveforms are dumped into two products: // - A xarapucadecoder-art.root file with the OpDetWaveforms as the product of this producer for further analysis. @@ -927,7 +937,19 @@ void sbndaq::SBNDXARAPUCADecoder::dump_waveforms(std::vector >& wvfms, const std::vector>& fragment_wvfms, uint32_t num_channels) { + if (wvfms.empty()) { + std::cout << "Empty waveforms, resizing to " << num_channels << " channels." << std::endl; + wvfms.resize(num_channels); + std::cout << "BEF COMB - wvfms_size = " << wvfms.size() << " x " << wvfms[0].size() << std::endl; + } + for (uint32_t ch = 0; ch < num_channels; ch++) { + wvfms[ch].insert(wvfms[ch].end(), fragment_wvfms[ch].begin(), fragment_wvfms[ch].end()); + } + std::cout << "AFT COMB - wvfms_size = " << wvfms.size() << " x " << wvfms[0].size() << std::endl; } /** diff --git a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl index 022a6888c..b9ab4ba0a 100644 --- a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl +++ b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl @@ -32,7 +32,7 @@ xarapucadecoder: # - Output data product instance name. waveforms_instance_name: "XARAPUCAChannels" # Name for the instance product containing the raw decoded waveforms. timing_ref_instance_name: "" # Name for the instance product containing the timing reference information. - store_debug_waveforms: 33 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). + store_debug_waveforms: 2 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). # - Debug options. debug_tdc_handle: false # (De)activates SPEC-TDC art::Handle information printing. debug_ptb_handle: false # (De)activates PTB art::Handle information printing. From c1a42c050f51eba1d4f0103edeeaf89b4f1b5b8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Tue, 14 Oct 2025 06:59:02 -0500 Subject: [PATCH 06/75] Combine all extended fragments succesfully --- .../XARAPUCA/SBNDXARAPUCADecoder_module.cc | 32 +++++++++---------- .../Decoders/XARAPUCA/xarapucadecoder.fcl | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index ff9b9c99f..61231e201 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -133,7 +133,7 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { bool fverbose; /**< If `true` it increases verbosity of console output for detailed processing steps. */ // Class methods. - void decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms); + void decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one); bool get_ptb_hlt_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t & timestamp, uint16_t & hlt_code); bool get_spec_tdc_etrig_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t & timestamp); @@ -310,6 +310,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) std::cout << "wvfms_size: " << wvfms.size() << std::endl; int32_t nominal_TTT = TTT_DEFAULT; uint64_t nominal_frag_timestamp = TTT_DEFAULT; + bool last_one = false; if (fverbose | fdebug_fragments_handle) std::cout << "\n > SBNDXARAPUCADecoder::produce: searching for V1740 fragments..." << std::endl; @@ -347,7 +348,8 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) for (size_t f = 0; f < num_caen_fragments; f++) { const artdaq::Fragment fragment = *container_fragment[f].get(); - decode_fragment(timestamp, nominal_frag_timestamp, nominal_TTT, fragment_indices, fragment, *prod_wvfms, wvfms); + last_one = f == (num_caen_fragments - 1); + decode_fragment(timestamp, nominal_frag_timestamp, nominal_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); } // End CAEN V1740 fragments loop. } } // End Container fragments loop. @@ -359,7 +361,8 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) // It searches for all CAEN V1740 fragments. for (size_t f = 0; f < frag_handle_size; f++) { const artdaq::Fragment fragment = fragment_handle->at(f); - decode_fragment(timestamp, nominal_frag_timestamp, nominal_TTT, fragment_indices, fragment, *prod_wvfms, wvfms); + last_one = f == (frag_handle_size - 1); + decode_fragment(timestamp, nominal_frag_timestamp, nominal_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); } // End CAEN V1740 fragments loop. } } // End extracting CAEN V1740 fragments. @@ -606,9 +609,7 @@ bool sbndaq::SBNDXARAPUCADecoder::get_ptb_hlt_timestamp(art::Event& e, uint64_t * */ -void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms) { - std::cout << "decode_wvfms_size: " << wvfms.size() << std::endl; - +void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one) { auto fragment_id = fragment.fragmentID() - ffragment_id_offset; auto it = std::find(fboard_id_list.begin(), fboard_id_list.end(), fragment_id); size_t board_idx; @@ -678,8 +679,6 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& std::cout << "\t Number of samples per group (this fragment): " << num_samples_per_group << std::endl; } - //std::vector > wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); - // =============== Extracts timing information for this fragment =============== // uint64_t frag_timestamp = fragment.timestamp(); // ns. @@ -694,13 +693,7 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& //// =============== Start decoding the waveforms =============== // std::vector > fragment_wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); decode_waveforms(fragment, fragment_wvfms, header_size, num_channels, num_samples_per_wvfm, num_words_per_wvfms, num_samples_per_group); -// - //// =============== Shifts timing to the selected timing reference frame =============== // -// - //shift_time(fragment, TTT_ticks, TTT_end_ns, timestamp, num_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); - //dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); - //combine_waveforms(wvfms, fragment_wvfms, num_channels); - + is_nominal_length = (num_nominal_samples_per_wvfm == num_samples_per_wvfm); is_first = (fragment_indices[board_idx] == 0); @@ -721,8 +714,15 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& std::cout << " EXTENDED fragment " << std::endl; combine_waveforms(wvfms, fragment_wvfms, num_channels); } - + fragment_indices[board_idx]++; + + if (last_one) { + std::cout << " LAST fragment " << std::endl; + shift_time(TTT_ticks, nominal_TTT, nominal_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); + dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); + } + } } diff --git a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl index b9ab4ba0a..774032157 100644 --- a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl +++ b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl @@ -32,7 +32,7 @@ xarapucadecoder: # - Output data product instance name. waveforms_instance_name: "XARAPUCAChannels" # Name for the instance product containing the raw decoded waveforms. timing_ref_instance_name: "" # Name for the instance product containing the timing reference information. - store_debug_waveforms: 2 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). + store_debug_waveforms: -1 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). # - Debug options. debug_tdc_handle: false # (De)activates SPEC-TDC art::Handle information printing. debug_ptb_handle: false # (De)activates PTB art::Handle information printing. From e1656068b0c2a39177683a04ae40e82dec54869e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Wed, 15 Oct 2025 06:06:52 -0500 Subject: [PATCH 07/75] Add new comments for code documenting. New variable for debugging the extended fragments combination --- .../XARAPUCA/SBNDXARAPUCADecoder_module.cc | 806 ++++++++++-------- .../Decoders/XARAPUCA/xarapucadecoder.fcl | 7 +- 2 files changed, 464 insertions(+), 349 deletions(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index 61231e201..7c46afb10 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -130,29 +130,36 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { bool fdebug_timing; /**< If `true` timing data is printed. */ bool fdebug_buffer; /**< If `true` the buffer status is printed. */ bool fdebug_waveforms; /**< If `true` waveforms decoding data is printed. */ + bool fdebug_extended_fragments; /**< If `true` extended fragments information is printed. */ bool fverbose; /**< If `true` it increases verbosity of console output for detailed processing steps. */ - // Class methods. + // Main processing method. void decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one); - bool get_ptb_hlt_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t & timestamp, uint16_t & hlt_code); - bool get_spec_tdc_etrig_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t & timestamp); + // Timing. void shift_time(uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t frag_timestamp, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp); - void decode_waveforms(const artdaq::Fragment& fragment, std::vector>& wvfms, size_t header_size, uint32_t num_channels, uint32_t num_samples_per_wvfm, uint32_t num_words_per_wvfms, uint32_t num_samples_per_group); - - void dump_waveforms(std::vector & prod_wvfms, std::vector>& wvfms, std::vector & fragment_indices, size_t board_index, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp); - void save_prod_wvfm(size_t board_idx, size_t ch, double ini_wvfm_timestamp, const std::vector > & wvfms, std::vector & prod_wvfms); - void save_debug_wvfm(size_t board_idx, size_t fragment_idx, int ch, double ini_wvfm_timestamp, double end_wvfm_timestamp, const std::vector > & wvfms); + bool get_spec_tdc_etrig_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t & timestamp); + bool get_ptb_hlt_timestamp(art::Event& e, uint64_t corr_raw_timestamp, uint64_t & timestamp, uint16_t & hlt_code); - void combine_waveforms(std::vector>& wvfms, const std::vector>& fragment_wvfms, uint32_t num_channels); - + // Waveforms decoding. + void decode_waveforms(const artdaq::Fragment& fragment, std::vector>& wvfms, size_t header_size, uint32_t num_channels, uint32_t num_samples_per_wvfm, uint32_t num_words_per_wvfms, uint32_t num_samples_per_group); uint16_t get_sample(uint64_t buffer, uint32_t msb, uint32_t lsb); uint32_t read_word(const uint32_t* & data_ptr); unsigned int get_channel_id(unsigned int board, unsigned int board_channel); - std::string print_timestamp(uint64_t timestamp); + // Combines decoded waveforms. + void combine_waveforms(std::vector>& wvfms, const std::vector>& fragment_wvfms, uint32_t num_channels); + + // Dumps and saves waveforms. + void dump_waveforms(std::vector & prod_wvfms, std::vector>& wvfms, std::vector & fragment_indices, size_t board_index, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp); + void save_prod_wvfm(size_t board_idx, size_t ch, double ini_wvfm_timestamp, const std::vector > & wvfms, std::vector & prod_wvfms); + void save_debug_wvfm(size_t board_idx, size_t fragment_idx, int ch, double ini_wvfm_timestamp, double end_wvfm_timestamp, const std::vector > & wvfms); + + // Auxiliary methods. int64_t signed_difference(uint64_t t1, uint64_t t2); uint64_t abs_difference(uint64_t t1, uint64_t t2); + std::string print_timestamp(uint64_t timestamp); + }; /** @@ -210,6 +217,7 @@ sbndaq::SBNDXARAPUCADecoder::SBNDXARAPUCADecoder(fhicl::ParameterSet const& p) fdebug_fragments_handle = p.get ("debug_fragments_handle", false); fdebug_timing = p.get ("debug_timing", false); fdebug_waveforms = p.get ("debug_waveforms", false); + fdebug_extended_fragments = p.get ("debug_extended_fragments", false); fdebug_buffer = p.get ("debug_buffer", false); fverbose = p.get ("verbose", false); @@ -229,8 +237,7 @@ sbndaq::SBNDXARAPUCADecoder::SBNDXARAPUCADecoder(fhicl::ParameterSet const& p) * 3. It searches for CAEN V1740 fragments in the event, decodes them and creates the output products: a vector of raw::OpDetWaveform. * 4. It dumps the products in the event. */ -void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) -{ +void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { if (fverbose) std::cout << "\n > SBNDXARAPUCADecoder::produce: entering the produce function." << std::endl; // Advances the event counter. @@ -307,7 +314,10 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) std::vector fragment_indices(fnum_caen_boards, 0); std::vector> wvfms; - std::cout << "wvfms_size: " << wvfms.size() << std::endl; + if (fdebug_extended_fragments) { + std::cout << " Waveforms size: " << wvfms.size() << std::endl; + } + int32_t nominal_TTT = TTT_DEFAULT; uint64_t nominal_frag_timestamp = TTT_DEFAULT; bool last_one = false; @@ -383,6 +393,241 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) } } +// =============== Main fragment processing method =============== // + +/** + * @brief Decodes a CAEN V1740 fragment, extracts the waveforms and combines them into the output product. + * @param[in] timestamp The valid timestamp used as reference for the event. + * @param[in,out] nominal_frag_timestamp The nominal timestamp calculated for the fragment being processed. + * @param[in,out] nominal_TTT The nominal Trigger Time Tag (TTT) calculated for the fragment being processed. + * @param[in,out] fragment_indices A vector containing the indices of the fragments already processed for each board. + * @param[in] fragment The artdaq::Fragment object to be processed. + * @param[in,out] prod_wvfms The vector of raw::OpDetWaveform objects to be filled with the decoded waveforms. + * @param[in,out] wvfms A 2D vector containing the waveforms for all channels and boards decoded so far. + * @param[in] last_one A boolean flag indicating if the fragment being processed is the last one in the event. + + * @details This method decodes a CAEN V1740 fragment, extracts the waveforms for each channel, shifts them in time according to the + * timing reference and combines them into the output product. + * 1. It checks if the fragment ID corresponds to a valid board. + * 2. It accesses the metadata and header of the fragment to get information about the number of channels, samples, words, etc. + * 3. It calculates the number of samples per waveform and checks if it is a nominal or extended fragment. + * 4. It decodes the waveforms for each channel in the fragment. + * 5. It shifts the waveforms in time according to the timing reference. + * 6. It combines the decoded waveforms into the output product. + * 7. It dumps the waveforms if required. + * + * @pre The art::Event object containing the fragment has been processed to get a valid timing reference. + * @post The vector of raw::OpDetWaveform objects is filled with the decoded waveforms from the fragment. + * @see shift_time + * @see decode_waveforms + * @see combine_waveforms + * @see dump_waveforms + */ + +void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one) { + auto fragment_id = fragment.fragmentID() - ffragment_id_offset; + auto it = std::find(fboard_id_list.begin(), fboard_id_list.end(), fragment_id); + size_t board_idx; + bool valid_fragment = false; + + if (it != fboard_id_list.end()) { + board_idx = it - fboard_id_list.begin(); + if (board_idx >= fnum_caen_boards) { + if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: fragment ID " << fragment_id << " (" << board_idx << ") is out of range. Skipping this fragment..." << std::endl; + } else { + valid_fragment = true; + } + } else { + if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: fragment ID " << fragment_id << " is not valid. Skipping this fragment..." << std::endl; + } + + if (valid_fragment) { + if (fverbose) std::cout << "\n > SBNDXARAPUCADecoder::decode_fragment: decoding V1740 CAEN fragment " << fragment_indices[board_idx] << " from the board " << board_idx << " (slot " << fboard_id_list[board_idx] << "):" << std::endl; + + bool is_nominal_length = false; + bool is_first = false; + + double ini_wvfm_timestamp = 0; + double end_wvfm_timestamp = 0; + + // =============== Accesses Event metadata and Event header for this fragment =============== // + + CAENV1740Fragment caen_fragment(fragment); + CAENV1740FragmentMetadata const* metadata = caen_fragment.Metadata(); + uint32_t num_channels = metadata->nChannels; + if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: number of channels: " << num_channels << std::endl; + + // Accesses the event and header data of the CAEN fragment. + CAENV1740Event const* event = caen_fragment.Event(); + CAENV1740EventHeader header = event->Header; + + // Gets the number of words of the header and the waveforms. + uint32_t num_words_per_event = header.eventSize; + size_t header_size = sizeof(CAENV1740EventHeader); + uint32_t num_words_per_header = header_size / sizeof(uint32_t); + uint32_t num_words_per_wvfms = (num_words_per_event - num_words_per_header); + + uint32_t num_bits_per_all_wvfms = num_words_per_wvfms * BITS_PER_WORD; + uint32_t num_samples_per_all_wvfms = num_bits_per_all_wvfms / BITS_PER_SAMPLE; + uint32_t num_remaining_bits = num_bits_per_all_wvfms % BITS_PER_SAMPLE; + uint32_t num_samples_per_wvfm = num_samples_per_all_wvfms / num_channels; + uint32_t num_samples_per_group = num_samples_per_wvfm * NUM_CHANNELS_PER_GROUP; + uint32_t num_nominal_samples_per_wvfm = metadata->nSamples; + + if (fverbose | fdebug_waveforms) { + if (num_nominal_samples_per_wvfm == num_samples_per_wvfm) { + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: [NOMINAL FRAGMENT] " << num_samples_per_wvfm << " samples/waveform." << " (" << num_samples_per_group << " samples per group - 8 channels per group -)." << std::endl; + } else { + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: [EXTENDED FRAGMENT] " << num_samples_per_wvfm << " samples/waveform." << " (" << num_samples_per_group << " samples per group - 8 channels per group -)." << std::endl; + } + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: nominal number of samples per waveform: " << num_nominal_samples_per_wvfm << "." << std::endl; + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: number of words for this fragment: " << num_words_per_event << " (Header: " << num_words_per_header << ", Waveform: " << num_words_per_wvfms << ") words." << std::endl; + } + + if (fdebug_waveforms) { + std::cout << "\t Number of bits for all the waveforms of this fragment: " << BITS_PER_WORD << "\t" << num_bits_per_all_wvfms << std::endl; + std::cout << "\t Number of samples for all the waveforms of this fragment: " << num_samples_per_all_wvfms << std::endl; + std::cout << "\t Number of remaining bits for this fragment: " << num_remaining_bits << std::endl; + std::cout << "\t Number of samples per wvfm (this fragment): " << num_samples_per_wvfm << std::endl; + std::cout << "\t Number of samples per group (this fragment): " << num_samples_per_group << std::endl; + } + + // =============== Extracts timing information for this fragment =============== // + + uint64_t frag_timestamp = fragment.timestamp(); // ns. + uint32_t TTT_ticks = header.triggerTime(); + int64_t TTT_end_ns = TTT_ticks * NANOSEC_PER_TICK; // ns. + + if (fdebug_timing) { + std::cout << "\t\t TTT header.extendedTriggerTime() [TTT_ticks] = " << header.extendedTriggerTime() << " ticks. \t TTT_end_ns = " << print_timestamp(header.extendedTriggerTime() * NANOSEC_PER_TICK) << "." << std::endl; + std::cout << "\t\t TTT header.triggerTimeRollOver(): " << header.triggerTimeRollOver() << std::endl; + } + + //// =============== Start decoding the waveforms =============== // + std::vector > fragment_wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); + decode_waveforms(fragment, fragment_wvfms, header_size, num_channels, num_samples_per_wvfm, num_words_per_wvfms, num_samples_per_group); + + is_nominal_length = (num_nominal_samples_per_wvfm == num_samples_per_wvfm); + is_first = (fragment_indices[board_idx] == 0); + + if (fverbose) { + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: processing the decoded fragment and combines the extended ones to their nominal ones if needed." << std::endl; + } + if (is_nominal_length) { + if (!is_first) { + if (fdebug_extended_fragments) { + std::cout << "\t\t NOT FIRST NOMINAL fragment " << std::endl; + std::cout << "\t\t nominal_TTT: " << nominal_TTT << " TTT_end_ns: " << TTT_end_ns << std::endl; + std::cout << "\t\t nominal_frag_timestamp: " << nominal_frag_timestamp << " frag_timestamp : " << frag_timestamp << std::endl; + } + shift_time(TTT_ticks, nominal_TTT, nominal_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); + dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); + } else { + if (fdebug_extended_fragments) std::cout << "\t\t FIRST NOMINAL fragment " << std::endl; + } + combine_waveforms(wvfms, fragment_wvfms, num_channels); + nominal_TTT = TTT_end_ns; + nominal_frag_timestamp = frag_timestamp; + } else { + if (fdebug_extended_fragments) std::cout << "\t\t EXTENDED fragment " << std::endl; + combine_waveforms(wvfms, fragment_wvfms, num_channels); + } + + fragment_indices[board_idx]++; + + if (last_one) { + if (fdebug_extended_fragments) std::cout << "\t\t LAST fragment " << std::endl; + shift_time(TTT_ticks, nominal_TTT, nominal_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); + dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); + } + } +} + +// =============== Timing functions =============== // + +/** + * @brief This function shifts the initial and end timestamps of a waveform based on the provided timing information. + * + * @param[in] TTT_ticks The trigger time tag in ticks from the CAEN V1740 header. + * @param[in] TTT_end_ns The end time of the Trigger Time Tag (TTT) in nanoseconds. + * @param[in] frag_timestamp The timestamp of the fragment in nanoseconds. + * @param[in] timestamp The reference timestamp (ETRIG from the SPEC-TDC or HLT from the PTB) in nanoseconds. + * @param[in] num_samples_per_wvfm The number of samples per waveform. + * @param[out] ini_wvfm_timestamp The initial timestamp of the waveform in microseconds (output). + * @param[out] end_wvfm_timestamp The end timestamp of the waveform in microseconds (output). + * + * @details + * This function calculates the initial and end timestamps for a waveform based on the provided timing information. It takes into account + * potential rollovers in the trigger time tag and adjusts the timestamps accordingly. The function supports different timing frames, including + * SPEC-TDC, PTB, and CAEN-only timing. The calculated timestamps are returned in microseconds. + * + * @see get_spec_tdc_etrig_timestamp + * @see get_ptb_hlt_timestamp + */ +void sbndaq::SBNDXARAPUCADecoder::shift_time(uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t frag_timestamp, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp) { + + int64_t pulse_duration_ns = num_samples_per_wvfm * fns_per_sample; // ns. + int64_t frag_timestamp_s = frag_timestamp / NANOSEC_IN_SEC; // s. + int64_t frag_timestamp_ns = frag_timestamp % NANOSEC_IN_SEC; // ns. + + // Gets the full TTT timestamp. + uint64_t full_TTT = 0; + // If the fragment timestamp is greater than the TTT end timestamp, it means that rollover occurred. + if (frag_timestamp_ns > TTT_end_ns) { + if (fverbose | fdebug_timing) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN TTT rollover occurred w.r.t. the fragment timestamp (FTS)." << std::endl; + full_TTT = (frag_timestamp_s + 1) * NANOSEC_IN_SEC + TTT_end_ns; + } else { + full_TTT = frag_timestamp_s * NANOSEC_IN_SEC + TTT_end_ns; + } + + int64_t ref_timestamp = 0; + + // If an ETRIG or HLT timestamp was found it restarts the time from it. Otherwise the CAEN time frame is assigned. + if (factive_timing_frame != CAEN_ONLY_TIMING) { + ref_timestamp = signed_difference(full_TTT, timestamp); // ns. + + ini_wvfm_timestamp = (ref_timestamp - pulse_duration_ns) * NANOSEC_TO_MICROSEC; // us. + end_wvfm_timestamp = ref_timestamp * NANOSEC_TO_MICROSEC; // us. + } else { + ref_timestamp = full_TTT; // ns. + + ini_wvfm_timestamp = ((ref_timestamp - pulse_duration_ns) % NANOSEC_IN_SEC) * NANOSEC_TO_MICROSEC; // ns. + end_wvfm_timestamp = (ref_timestamp % NANOSEC_IN_SEC) * NANOSEC_TO_MICROSEC; // us. + } + + if (fdebug_timing) { + std::cout << std::fixed << std::setprecision(0); + std::cout << "\t\t ns/tick = " << NANOSEC_PER_TICK << ", ns/sample = " << fns_per_sample << std::endl; + std::cout << "\t\t TTT header.TriggerTime() [TTT_ticks] = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; + std::cout << "\t\t Full Fragment timestamp: " << print_timestamp(frag_timestamp) << " = " << frag_timestamp_s << " s " << frag_timestamp_ns << " ns." << std::endl; + std::cout << "\t\t Full TTT - fragment timestamp = "<< abs_difference(full_TTT, frag_timestamp) << " ns." << " Post-percent: " << (double(abs_difference(full_TTT, frag_timestamp)) / double(pulse_duration_ns)) * 100 << "%." << std::endl; + if (factive_timing_frame == SPEC_TDC_TIMING) { + std::cout << "\t ETRIG (SPEC-TDC) timestamp of the fragment: " << std::endl; + std::cout << "\t\t Full UTC ETRIG timestamp: " << print_timestamp(timestamp) << "." << std::endl; + std::cout << "\t\t ETRIG SPEC-TDC difference applied to the CAEN frame (full timestamps): " << print_timestamp(full_TTT) << " - " << print_timestamp(timestamp) << " = " << ref_timestamp << " ns." << std::endl; + } else if (factive_timing_frame == PTB_TIMING) { + std::cout << "\t HLT ETRIG (PTB) timestamp of the fragment: " << std::endl; + std::cout << "\t\t Full UTC HLT ETRIG timestamp: " << print_timestamp(timestamp) << "." << std::endl; + std::cout << "\t\t HLT ETRIG (PTB) difference applied to the CAEN frame (full timestamps): " << print_timestamp(full_TTT) << " - " << print_timestamp(timestamp) << " = " << ref_timestamp << " ns." << std::endl; + } else if (factive_timing_frame == CAEN_ONLY_TIMING) { + std::cout << "\t CAEN trigger timestamp (TTT) of the fragment: " << std::endl; + std::cout << "\t\t Full UTC TTT timestamp: " << print_timestamp(full_TTT) << " = " << full_TTT / NANOSEC_IN_SEC << " s " << TTT_end_ns << " ns." << std::endl; + } + } + + if (fverbose | fdebug_timing) { + std::cout << std::fixed << std::setprecision(3); + if (factive_timing_frame == SPEC_TDC_TIMING) { + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: SPEC-TDC time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; + } else if (factive_timing_frame == PTB_TIMING) { + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: PTB time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; + } else { // CAEN_ONLY_TIMING + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; + } + std::cout << " > SBNDXARAPUCADecoder::decode_fragment: TTT_end_ticks = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; + } +} + /** * @brief Searches for the SPEC-TDC ETRIG timestamp closest to the raw timestamp if any SPEC-TDC ETRIG product is found in the event. * @param[in] e The event to be processed. @@ -577,153 +822,226 @@ bool sbndaq::SBNDXARAPUCADecoder::get_ptb_hlt_timestamp(art::Event& e, uint64_t return hlt_found; } +// =============== Decodes the waveforms =============== // + /** - * @brief This function processes a single fragment from a CAEN V1740 and stores the decoded waveforms in the provided product - * container. + * @brief Decodes the waveforms from a CAEN V1740 fragment (binary decoding stage). * - * @param[in,out] fragment_indices A 1D vector tracking the number of fragments processed for each board. * @param[in] fragment The input CAEN V1740 fragment containing raw data to be decoded. - * @param[out] prod_wvfms Vector where the decoded waveforms will be stored as raw::OpDetWaveform objects. - * - * @details - * - Identifies the board index corresponding to the fragment ID. - * - Verifies the fragment ID against known boards and ensures it is within a valid range. - * - - * - Decodes the fragment reading raw 32-bit words from the fragment, storing them in a buffer, - * and extracting 12-bit samples. The decoding includes: - * - Accessing metadata for the number of channels and samples. - * - Getting the initial timestamp with respect to the selected timing frame. - * - Binary decoding of the raw waveform. To assign efficiently each sequential sample extracted. These indices formulas are - * applied: - * - The board channel index: - * \f[ - * c = \left( \frac{S}{3} \mod 8 \right) + g \times 8 - * \f] - * - The channel sample index: - * \f[ - * s = (S \mod 3) + \left( \frac{S}{24} \times 3 \right) \mod s_{w}} - * \f] - * Where the group index is computed as \f$ \frac{S}{s_{g}} \f$. - * - Mapping samples to corresponding channels. - * - Populates the output vector (`prod_wvfms`) with decoded waveforms and optionally generates debug waveforms output. + * @param[out] wvfms A 2D vector where the decoded waveforms will be stored. Each inner vector corresponds to a channel's waveform. + * @param[in] header_size The size of the event header in bytes. + * @param[in] num_channels The number of channels in the fragment. + * @param[in] num_samples_per_wvfm The number of samples per waveform for each channel. + * @param[in] num_words_per_wvfms The total number of 32-bit words containing waveform data in the fragment. + * @param[in] num_samples_per_group The number of samples per group of channels (8 channels per group). * + * @details This function reads raw 32-bit words from the fragment, storing them in a buffer, and extracts 12-bit samples. + * It assigns each sample to the appropriate channel and sample index based on its position in the sequence. The decoding process includes: + * - Initializing a buffer to hold incoming data and tracking the number of bits currently stored. + * - Iterating over each 32-bit word in the waveform data section of the fragment, adding it to the buffer. + * - Extracting 12-bit samples from the buffer as long as there are enough bits available, and assigning them to their respective channels and sample indices using calculated formulas. + * The function ensures that all samples are correctly mapped to their channels, taking into account the grouping of channels and the interleaving of samples. + * @note The function assumes that the input fragment is valid and contains the expected structure for a CAEN V1740 device. + * @see SBN Document 38475-v1 for more details on the binary decoding. */ +void sbndaq::SBNDXARAPUCADecoder::decode_waveforms(const artdaq::Fragment& fragment, std::vector>& wvfms, size_t header_size, uint32_t num_channels, uint32_t num_samples_per_wvfm, uint32_t num_words_per_wvfms, uint32_t num_samples_per_group) { + // =============== Start decoding the waveforms =============== // + if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding of the waveforms starting... " << std::endl; + + // Absolute sample number [0, TOTAL_NUM_SAMPLES] where TOTAL_NUM_SAMPLES is the total number of samples stored for an event. + uint32_t S = 0; + // Buffer variables. + uint64_t buffer = 0; + uint32_t bits_in_buffer = 0; -void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one) { - auto fragment_id = fragment.fragmentID() - ffragment_id_offset; - auto it = std::find(fboard_id_list.begin(), fboard_id_list.end(), fragment_id); - size_t board_idx; - bool valid_fragment = false; - - if (it != fboard_id_list.end()) { - board_idx = it - fboard_id_list.begin(); - if (board_idx >= fnum_caen_boards) { - if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: fragment ID " << fragment_id << " (" << board_idx << ") is out of range. Skipping this fragment..." << std::endl; - } else { - valid_fragment = true; - } - } else { - if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: fragment ID " << fragment_id << " is not valid. Skipping this fragment..." << std::endl; - } - - if (valid_fragment) { - if (fverbose) std::cout << "\n > SBNDXARAPUCADecoder::decode_fragment: decoding V1740 CAEN fragment " << fragment_indices[board_idx] << " from the board " << board_idx << " (slot " << fboard_id_list[board_idx] << "):" << std::endl; - - bool is_nominal_length = false; - //bool is_within_nominal_length = false; - bool is_first = false; - + // Data pointer to the beggining of the waveforms stores in the event. + const uint32_t* data_ptr = reinterpret_cast(fragment.dataBeginBytes() + header_size); + // Accesses each word, stores it in the buffer and then the samples are extracted from the buffer. + for (size_t j = 0; j < num_words_per_wvfms; j++) { + uint64_t word = read_word(data_ptr); - double ini_wvfm_timestamp = 0; - double end_wvfm_timestamp = 0; - - // =============== Accesses Event metadata and Event header for this fragment =============== // + // Adds the new word to the buffer and increments the number of bits stored in it. + if (fdebug_buffer) std::cout << buffer << "[word: " << word << "]" << std::endl; + buffer |= word << bits_in_buffer; + bits_in_buffer += BITS_PER_WORD; // bytes * 8 bits/byte + if (fdebug_buffer) std::cout << " +" << buffer << " [bits in buffer: "<< bits_in_buffer << "]" << std::endl; - CAENV1740Fragment caen_fragment(fragment); - CAENV1740FragmentMetadata const* metadata = caen_fragment.Metadata(); - uint32_t num_channels = metadata->nChannels; - if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: number of channels: " << num_channels << std::endl; - - // Accesses the event and header data of the CAEN fragment. - CAENV1740Event const* event = caen_fragment.Event(); - CAENV1740EventHeader header = event->Header; - - // Gets the number of words of the header and the waveforms. - uint32_t num_words_per_event = header.eventSize; - size_t header_size = sizeof(CAENV1740EventHeader); - uint32_t num_words_per_header = header_size / sizeof(uint32_t); - uint32_t num_words_per_wvfms = (num_words_per_event - num_words_per_header); - - uint32_t num_bits_per_all_wvfms = num_words_per_wvfms * BITS_PER_WORD; - uint32_t num_samples_per_all_wvfms = num_bits_per_all_wvfms / BITS_PER_SAMPLE; - uint32_t num_remaining_bits = num_bits_per_all_wvfms % BITS_PER_SAMPLE; - uint32_t num_samples_per_wvfm = num_samples_per_all_wvfms / num_channels; - uint32_t num_samples_per_group = num_samples_per_wvfm * NUM_CHANNELS_PER_GROUP; - uint32_t num_nominal_samples_per_wvfm = metadata->nSamples; - - if (fverbose | fdebug_waveforms) { - if (num_nominal_samples_per_wvfm == num_samples_per_wvfm) { - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: [NOMINAL FRAGMENT] " << num_samples_per_wvfm << " samples/waveform." << " (" << num_samples_per_group << " samples per group - 8 channels per group -)." << std::endl; - } else { - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: [EXTENDED FRAGMENT] " << num_samples_per_wvfm << " samples/waveform." << " (" << num_samples_per_group << " samples per group - 8 channels per group -)." << std::endl; - } - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: nominal number of samples per waveform: " << num_nominal_samples_per_wvfm << "." << std::endl; - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: number of words for this fragment: " << num_words_per_event << " (Header: " << num_words_per_header << ", Waveform: " << num_words_per_wvfms << ") words." << std::endl; + // Obtains 12-bit sequences from the buffer and assigns each sample to the channel and channel sample it belongs to. + while (bits_in_buffer >= BITS_PER_SAMPLE) { + // Computes board channel, channel sample and group channel and assigns the sample to those indices. + uint32_t g = (S / num_samples_per_group); // Group index. + uint32_t c = ((S / NUM_CONSECUTIVE_SAMPLES) % NUM_CHANNELS_PER_GROUP) + g * NUM_GROUPS; // Channel index. + uint32_t s = (S % NUM_CONSECUTIVE_SAMPLES) + ((S / NUM_SAMPLES_PER_ROUND) * NUM_CONSECUTIVE_SAMPLES) % num_samples_per_wvfm; // Sample/channel index. + uint16_t sample = get_sample(buffer, BITS_PER_SAMPLE - 1, 0); + wvfms[c][s] = sample; + if (fdebug_waveforms) std::cout << "\tSample: " << sample << "\tg: " << g << "\tch: " << c << "\ts:" << s << "\tS: " << S << std::endl; + + // Updates the buffer status removing the read bits and decreasing the number of bits stored in it. + buffer >>= BITS_PER_SAMPLE; + bits_in_buffer -= BITS_PER_SAMPLE; + if (fdebug_buffer) std::cout << " -" << buffer << " [bits in buffer: "<< bits_in_buffer << "]" << std::endl; + + // Increments the absolute sample step. + S++; } + } +} - if (fdebug_waveforms) { - std::cout << "\t Number of bits for all the waveforms of this fragment: " << BITS_PER_WORD << "\t" << num_bits_per_all_wvfms << std::endl; - std::cout << "\t Number of samples for all the waveforms of this fragment: " << num_samples_per_all_wvfms << std::endl; - std::cout << "\t Number of remaining bits for this fragment: " << num_remaining_bits << std::endl; - std::cout << "\t Number of samples per wvfm (this fragment): " << num_samples_per_wvfm << std::endl; - std::cout << "\t Number of samples per group (this fragment): " << num_samples_per_group << std::endl; - } +/** + * @brief Extract a sample from a 64-bit buffer using the specified bit positions. + * + * @param[in] buffer An unsigned 64-bit integer which represents a temporal buffer for the read words and where the samples are extracted from. + * @param[in] msb An unsigned 32-bit integer representing the most significative bit (MSB) where the readout from the buffer paramter. + * @param[in] lsb An unsigned 32-bit integer representing the less significative bit (LSB) from we end read + * + * @details The function shifts the buffer to the right by the number of positions specified by `lsb` so that the least significant bit of the + * sample aligns with bit 0. It then applies a mask to isolate the bits between `lsb` and `msb`, inclusive. + * + * @return The extracted sample as a 16-bit unsigned integer. + */ +uint16_t sbndaq::SBNDXARAPUCADecoder::get_sample(uint64_t buffer, uint32_t msb, uint32_t lsb) { + uint64_t mask = (1U << (msb - lsb + 1)) - 1; + uint64_t sample = buffer >> lsb; + return sample & mask; +} - // =============== Extracts timing information for this fragment =============== // +/** + * @brief Read a 32-bit word from the data pointer and advances the pointer. + * + * @param[in, out] data_ptr A reference to a pointer pointing to the current position in the data. + * + * @details This function retrieves a 32-bit word from the memory location pointed to by `data_ptr`. After reading, it advances `data_ptr` to + * the next 32-bit word location. + * + * @return The 32-bit word read from the location pointed to by `data_ptr`. + */ +uint32_t sbndaq::SBNDXARAPUCADecoder::read_word(const uint32_t* & data_ptr) { + uint32_t word = *data_ptr; + data_ptr += 1; + return word; +} - uint64_t frag_timestamp = fragment.timestamp(); // ns. - uint32_t TTT_ticks = header.triggerTime(); - int64_t TTT_end_ns = TTT_ticks * NANOSEC_PER_TICK; // ns. +/** + * @brief Generates a unique global channel identifier using the board slot and the channel number of that board. + * + * @param[in] board Index of the board in `fboard_id_list` from which to derive the board slot. + * @param[in] board_channel The specific channel number on the given board. + * + * @details This function computes a `channel_id` by combining the board slot and the specific + * channel number on that board. + * The unique identifier `channel_id` (\f$ CH_{ID} $\f) is computed as follows: + * \f[ + * CH\_{ID} = B\_{ID} \times 100 + CH\_{B} + * \f] + * + * Where: + * - \f$ B\_{ID} \f$ is the fragment ID retrieved from `fboard_id_list` based on the slot. + * - \f$ CH\_B \f$ is the channel number on that board. + * + * @return A unique identifier for the specified channel as an unsigned integer. + */ +unsigned int sbndaq::SBNDXARAPUCADecoder::get_channel_id(unsigned int board, unsigned int board_channel) { + unsigned int channel_id = fboard_id_list[board] * 100 + board_channel; + return channel_id; +} - if (fdebug_timing) { - std::cout << "\t\t TTT header.extendedTriggerTime() [TTT_ticks] = " << header.extendedTriggerTime() << " ticks. \t TTT_end_ns = " << print_timestamp(header.extendedTriggerTime() * NANOSEC_PER_TICK) << "." << std::endl; - std::cout << "\t\t TTT header.triggerTimeRollOver(): " << header.triggerTimeRollOver() << std::endl; +// =============== Combines the waveforms from extended fragments =============== // + +/** + * @brief Combines the waveforms from the current fragment with the previously stored waveforms. + * @param[in,out] wvfms A 2D vector containing the (combined if it was needed before) waveforms. + * @param[in] fragment_wvfms A 2D vector containing the waveforms from the current fragment to be combined. + * @param[in] num_channels The number of channels per board. + * + * @details + * The function performs the following steps: + * 1. Checks if the `wvfms` vector is empty. If it is, it resizes it to accommodate `num_channels` channels. + * 2. Iterates over each channel from 0 to `num_channels - 1`. + * 3. For each channel, it appends the samples from `fragment_wvfms` to the corresponding channel in `wvfms`. + * + * This approach ensures that waveforms from multiple fragments are concatenated correctly, maintaining the order of samples for each channel. + * + * @pre The `fragment_wvfms` vector should contain waveforms for all channels of the board being processed. + * @pre The `wvfms` vector should be either empty or already contain waveforms for all channels of the board being processed. + */ +void sbndaq::SBNDXARAPUCADecoder::combine_waveforms(std::vector>& wvfms, const std::vector>& fragment_wvfms, uint32_t num_channels) { + if (fdebug_extended_fragments) std::cout << " > SBNDXARAPUCADecoder::combine_waveforms: combining waveforms from extended fragments..." << std::endl; + if (wvfms.empty()) { + if (fdebug_extended_fragments) { + std::cout << "\t\t Empty waveforms, resizing to " << num_channels << " channels." << std::endl; + } + wvfms.resize(num_channels); + if (fverbose | fdebug_extended_fragments) { + std::cout << "\t\t Waveforms size BEFORE combining = " << wvfms.size() << " x " << wvfms[0].size() << std::endl; + } + } + for (uint32_t ch = 0; ch < num_channels; ch++) { + wvfms[ch].insert(wvfms[ch].end(), fragment_wvfms[ch].begin(), fragment_wvfms[ch].end()); + } + if (fverbose | fdebug_extended_fragments) { + std::cout << "\t\t Waveforms size AFTER combining = " << wvfms.size() << " x " << wvfms[0].size() << std::endl; } +} - //// =============== Start decoding the waveforms =============== // - std::vector > fragment_wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); - decode_waveforms(fragment, fragment_wvfms, header_size, num_channels, num_samples_per_wvfm, num_words_per_wvfms, num_samples_per_group); - - is_nominal_length = (num_nominal_samples_per_wvfm == num_samples_per_wvfm); - is_first = (fragment_indices[board_idx] == 0); +// =============== Dumps the decoded waveforms =============== // + +/** + * @brief Dump products into a `raw::OpDetWaveform` object and into a debug histogram file. + * @param[in,out] prod_wvfms A reference to the vector where the produced `raw::OpDetWaveform` objects are dumped into products. + * @param[in,out] wvfms A 2D vector containing the (combined if needed) waveforms. + * @param[in,out] fragment_indices A reference to a vector keeping track of the number of fragments decoded per board. + * @param[in] board_idx The board index (position in the list of boards). + * @param[in] num_channels The number of channels per board. + * @param[in] ini_wvfm_timestamp The initial timestamp of the waveform in microseconds. + * @param[in] end_wvfm_timestamp The final timestamp of the waveform in microseconds. + * + * @details + * The function performs the following steps: + * 1. Determines the number of debug waveforms to be stored based on the configuration parameter `fstore_debug_waveforms`. + * - If `fstore_debug_waveforms` is set to -1, all channels are considered for debug storage. + * - Otherwise, it takes the minimum between `num_channels` and `fstore_debug_waveforms`. + * 2. Iterates over each channel up to the determined number of debug waveforms: + * - Calls `save_prod_wvfm` to convert and store the waveform in the products. + * - Calls `save_debug_wvfm` to save the waveform as a histogram for debugging purposes. + * 3. For any remaining channels beyond the debug limit, it only calls `save_prod_wvfm` to store the waveform in the products. + * 4. Clears the `wvfms` vector to free up memory after processing. + * + * @pre ini_wvfm_timestamp and end_wvfm_timestamp is assumed to be given in microseconds when the timing frame is not CAEN_ONLY_TIMING. + * @pre The `wvfms` vector should contain waveforms for all channels of the board specified by `board_idx`. + * @pre The `fragment_indices` vector should have been initialized with a size equal to the number of boards being processed. + * @pre The `prod_wvfms` vector should be ready to accept new `raw::OpDetWaveform` objects. + * + * @see raw::OpDetWaveform + * @see save_prod_wvfm + * @see save_debug_wvfm + */ +void sbndaq::SBNDXARAPUCADecoder::dump_waveforms(std::vector & prod_wvfms, std::vector>& wvfms, std::vector & fragment_indices, size_t board_idx, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp) { - if (is_nominal_length) { - if (!is_first) { - std::cout << " NOT FIRST NOMINAL fragment " << std::endl; - std::cout << " nominal_TTT: " << nominal_TTT << " TTT_end_ns: " << TTT_end_ns << std::endl; - std::cout << " nominal_frag_timestamp: " << nominal_frag_timestamp << " frag_timestamp : " << frag_timestamp << std::endl; - shift_time(TTT_ticks, nominal_TTT, nominal_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); - dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); - } else { - std::cout << " FIRST NOMINAL fragment " << std::endl; - } - combine_waveforms(wvfms, fragment_wvfms, num_channels); - nominal_TTT = TTT_end_ns; - nominal_frag_timestamp = frag_timestamp; - } else { - std::cout << " EXTENDED fragment " << std::endl; - combine_waveforms(wvfms, fragment_wvfms, num_channels); - } + // The decoded waveforms are dumped into two products: + // - A xarapucadecoder-art.root file with the OpDetWaveforms as the product of this producer for further analysis. + // - A decoder_hist.root file gathering a waveform histograms. + if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding complete, dumping products..." << std::endl; - fragment_indices[board_idx]++; + uint32_t num_debug_wvfms; - if (last_one) { - std::cout << " LAST fragment " << std::endl; - shift_time(TTT_ticks, nominal_TTT, nominal_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); - dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); - } + if (fstore_debug_waveforms == -1) { + num_debug_wvfms = num_channels; + } else { + num_debug_wvfms = std::min(num_channels, fstore_debug_waveforms); + } + + uint32_t ch; + + for (ch = 0; ch < num_debug_wvfms; ch++) { + save_prod_wvfm(board_idx, ch, ini_wvfm_timestamp, wvfms, prod_wvfms); + save_debug_wvfm(board_idx, fragment_indices[board_idx], ch, ini_wvfm_timestamp, end_wvfm_timestamp, wvfms); + } + for (;ch < num_channels; ch++) { + save_prod_wvfm(board_idx, ch, ini_wvfm_timestamp, wvfms, prod_wvfms); } + + wvfms.clear(); } /** @@ -804,211 +1122,7 @@ void sbndaq::SBNDXARAPUCADecoder::save_debug_wvfm(size_t board_idx, size_t fragm } -void sbndaq::SBNDXARAPUCADecoder::shift_time(uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t frag_timestamp, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp) { - - int64_t pulse_duration_ns = num_samples_per_wvfm * fns_per_sample; // ns. - int64_t frag_timestamp_s = frag_timestamp / NANOSEC_IN_SEC; // s. - int64_t frag_timestamp_ns = frag_timestamp % NANOSEC_IN_SEC; // ns. - - // Gets the full TTT timestamp. - uint64_t full_TTT = 0; - // If the fragment timestamp is greater than the TTT end timestamp, it means that rollover occurred. - if (frag_timestamp_ns > TTT_end_ns) { - if (fverbose | fdebug_timing) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN TTT rollover occurred w.r.t. the fragment timestamp (FTS)." << std::endl; - full_TTT = (frag_timestamp_s + 1) * NANOSEC_IN_SEC + TTT_end_ns; - } else { - full_TTT = frag_timestamp_s * NANOSEC_IN_SEC + TTT_end_ns; - } - - int64_t ref_timestamp = 0; - - // If an ETRIG or HLT timestamp was found it restarts the time from it. Otherwise the CAEN time frame is assigned. - if (factive_timing_frame != CAEN_ONLY_TIMING) { - ref_timestamp = signed_difference(full_TTT, timestamp); // ns. - - ini_wvfm_timestamp = (ref_timestamp - pulse_duration_ns) * NANOSEC_TO_MICROSEC; // us. - end_wvfm_timestamp = ref_timestamp * NANOSEC_TO_MICROSEC; // us. - } else { - ref_timestamp = full_TTT; // ns. - - ini_wvfm_timestamp = ((ref_timestamp - pulse_duration_ns) % NANOSEC_IN_SEC) * NANOSEC_TO_MICROSEC; // ns. - end_wvfm_timestamp = (ref_timestamp % NANOSEC_IN_SEC) * NANOSEC_TO_MICROSEC; // us. - } - - if (fdebug_timing) { - std::cout << std::fixed << std::setprecision(0); - std::cout << "\t\t ns/tick = " << NANOSEC_PER_TICK << ", ns/sample = " << fns_per_sample << std::endl; - std::cout << "\t\t TTT header.TriggerTime() [TTT_ticks] = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; - std::cout << "\t\t Full Fragment timestamp: " << print_timestamp(frag_timestamp) << " = " << frag_timestamp_s << " s " << frag_timestamp_ns << " ns." << std::endl; - std::cout << "\t\t Full TTT - fragment timestamp = "<< abs_difference(full_TTT, frag_timestamp) << " ns." << " Post-percent: " << (double(abs_difference(full_TTT, frag_timestamp)) / double(pulse_duration_ns)) * 100 << "%." << std::endl; - if (factive_timing_frame == SPEC_TDC_TIMING) { - std::cout << "\t ETRIG (SPEC-TDC) timestamp of the fragment: " << std::endl; - std::cout << "\t\t Full UTC ETRIG timestamp: " << print_timestamp(timestamp) << "." << std::endl; - std::cout << "\t\t ETRIG SPEC-TDC difference applied to the CAEN frame (full timestamps): " << print_timestamp(full_TTT) << " - " << print_timestamp(timestamp) << " = " << ref_timestamp << " ns." << std::endl; - } else if (factive_timing_frame == PTB_TIMING) { - std::cout << "\t HLT ETRIG (PTB) timestamp of the fragment: " << std::endl; - std::cout << "\t\t Full UTC HLT ETRIG timestamp: " << print_timestamp(timestamp) << "." << std::endl; - std::cout << "\t\t HLT ETRIG (PTB) difference applied to the CAEN frame (full timestamps): " << print_timestamp(full_TTT) << " - " << print_timestamp(timestamp) << " = " << ref_timestamp << " ns." << std::endl; - } else if (factive_timing_frame == CAEN_ONLY_TIMING) { - std::cout << "\t CAEN trigger timestamp (TTT) of the fragment: " << std::endl; - std::cout << "\t\t Full UTC TTT timestamp: " << print_timestamp(full_TTT) << " = " << full_TTT / NANOSEC_IN_SEC << " s " << TTT_end_ns << " ns." << std::endl; - } - } - - if (fverbose | fdebug_timing) { - std::cout << std::fixed << std::setprecision(3); - if (factive_timing_frame == SPEC_TDC_TIMING) { - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: SPEC-TDC time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; - } else if (factive_timing_frame == PTB_TIMING) { - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: PTB time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; - } else { // CAEN_ONLY_TIMING - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN time window of " << end_wvfm_timestamp - ini_wvfm_timestamp << " us: [" << ini_wvfm_timestamp << ", " << end_wvfm_timestamp << "] us." << std::endl; - } - std::cout << " > SBNDXARAPUCADecoder::decode_fragment: TTT_end_ticks = " << TTT_ticks << " ticks. \t TTT_end_ns = " << print_timestamp(TTT_end_ns) << "." << std::endl; - } -} - -void sbndaq::SBNDXARAPUCADecoder::decode_waveforms(const artdaq::Fragment& fragment, std::vector>& wvfms, size_t header_size, uint32_t num_channels, uint32_t num_samples_per_wvfm, uint32_t num_words_per_wvfms, uint32_t num_samples_per_group) { - // =============== Start decoding the waveforms =============== // - if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding of the waveforms starting... " << std::endl; - - // Absolute sample number [0, TOTAL_NUM_SAMPLES] where TOTAL_NUM_SAMPLES is the total number of samples stored for an event. - uint32_t S = 0; - // Buffer variables. - uint64_t buffer = 0; - uint32_t bits_in_buffer = 0; - - // Data pointer to the beggining of the waveforms stores in the event. - const uint32_t* data_ptr = reinterpret_cast(fragment.dataBeginBytes() + header_size); - // Accesses each word, stores it in the buffer and then the samples are extracted from the buffer. - for (size_t j = 0; j < num_words_per_wvfms; j++) { - uint64_t word = read_word(data_ptr); - - // Adds the new word to the buffer and increments the number of bits stored in it. - if (fdebug_buffer) std::cout << buffer << "[word: " << word << "]" << std::endl; - buffer |= word << bits_in_buffer; - bits_in_buffer += BITS_PER_WORD; // bytes * 8 bits/byte - if (fdebug_buffer) std::cout << " +" << buffer << " [bits in buffer: "<< bits_in_buffer << "]" << std::endl; - - // Obtains 12-bit sequences from the buffer and assigns each sample to the channel and channel sample it belongs to. - while (bits_in_buffer >= BITS_PER_SAMPLE) { - // Computes board channel, channel sample and group channel and assigns the sample to those indices. - uint32_t g = (S / num_samples_per_group); // Group index. - uint32_t c = ((S / NUM_CONSECUTIVE_SAMPLES) % NUM_CHANNELS_PER_GROUP) + g * NUM_GROUPS; // Channel index. - uint32_t s = (S % NUM_CONSECUTIVE_SAMPLES) + ((S / NUM_SAMPLES_PER_ROUND) * NUM_CONSECUTIVE_SAMPLES) % num_samples_per_wvfm; // Sample/channel index. - uint16_t sample = get_sample(buffer, BITS_PER_SAMPLE - 1, 0); - wvfms[c][s] = sample; - if (fdebug_waveforms) std::cout << "\tSample: " << sample << "\tg: " << g << "\tch: " << c << "\ts:" << s << "\tS: " << S << std::endl; - - // Updates the buffer status removing the read bits and decreasing the number of bits stored in it. - buffer >>= BITS_PER_SAMPLE; - bits_in_buffer -= BITS_PER_SAMPLE; - if (fdebug_buffer) std::cout << " -" << buffer << " [bits in buffer: "<< bits_in_buffer << "]" << std::endl; - - // Increments the absolute sample step. - S++; - } - } -} - -void sbndaq::SBNDXARAPUCADecoder::dump_waveforms(std::vector & prod_wvfms, std::vector>& wvfms, std::vector & fragment_indices, size_t board_idx, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp) { - - // The decoded waveforms are dumped into two products: - // - A xarapucadecoder-art.root file with the OpDetWaveforms as the product of this producer for further analysis. - // - A decoder_hist.root file gathering a waveform histograms. - if (fverbose) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: binary decoding complete, dumping products..." << std::endl; - - uint32_t num_debug_wvfms; - - if (fstore_debug_waveforms == -1) { - num_debug_wvfms = num_channels; - } else { - num_debug_wvfms = std::min(num_channels, fstore_debug_waveforms); - } - - uint32_t ch; - - for (ch = 0; ch < num_debug_wvfms; ch++) { - save_prod_wvfm(board_idx, ch, ini_wvfm_timestamp, wvfms, prod_wvfms); - save_debug_wvfm(board_idx, fragment_indices[board_idx], ch, ini_wvfm_timestamp, end_wvfm_timestamp, wvfms); - } - - for (;ch < num_channels; ch++) { - save_prod_wvfm(board_idx, ch, ini_wvfm_timestamp, wvfms, prod_wvfms); - } - - wvfms.clear(); -} - -void sbndaq::SBNDXARAPUCADecoder::combine_waveforms(std::vector>& wvfms, const std::vector>& fragment_wvfms, uint32_t num_channels) { - if (wvfms.empty()) { - std::cout << "Empty waveforms, resizing to " << num_channels << " channels." << std::endl; - wvfms.resize(num_channels); - std::cout << "BEF COMB - wvfms_size = " << wvfms.size() << " x " << wvfms[0].size() << std::endl; - } - for (uint32_t ch = 0; ch < num_channels; ch++) { - wvfms[ch].insert(wvfms[ch].end(), fragment_wvfms[ch].begin(), fragment_wvfms[ch].end()); - } - std::cout << "AFT COMB - wvfms_size = " << wvfms.size() << " x " << wvfms[0].size() << std::endl; -} - -/** - * @brief Extract a sample from a 64-bit buffer using the specified bit positions. - * - * @param[in] buffer An unsigned 64-bit integer which represents a temporal buffer for the read words and where the samples are extracted from. - * @param[in] msb An unsigned 32-bit integer representing the most significative bit (MSB) where the readout from the buffer paramter. - * @param[in] lsb An unsigned 32-bit integer representing the less significative bit (LSB) from we end read - * - * @details The function shifts the buffer to the right by the number of positions specified by `lsb` so that the least significant bit of the - * sample aligns with bit 0. It then applies a mask to isolate the bits between `lsb` and `msb`, inclusive. - * - * @return The extracted sample as a 16-bit unsigned integer. - */ -uint16_t sbndaq::SBNDXARAPUCADecoder::get_sample(uint64_t buffer, uint32_t msb, uint32_t lsb) { - uint64_t mask = (1U << (msb - lsb + 1)) - 1; - uint64_t sample = buffer >> lsb; - return sample & mask; -} - -/** - * @brief Read a 32-bit word from the data pointer and advances the pointer. - * - * @param[in, out] data_ptr A reference to a pointer pointing to the current position in the data. - * - * @details This function retrieves a 32-bit word from the memory location pointed to by `data_ptr`. After reading, it advances `data_ptr` to - * the next 32-bit word location. - * - * @return The 32-bit word read from the location pointed to by `data_ptr`. - */ -uint32_t sbndaq::SBNDXARAPUCADecoder::read_word(const uint32_t* & data_ptr) { - uint32_t word = *data_ptr; - data_ptr += 1; - return word; -} - -/** - * @brief Generates a unique global channel identifier using the board slot and the channel number of that board. - * - * @param[in] board Index of the board in `fboard_id_list` from which to derive the board slot. - * @param[in] board_channel The specific channel number on the given board. - * - * @details This function computes a `channel_id` by combining the board slot and the specific - * channel number on that board. - * The unique identifier `channel_id` (\f$ CH_{ID} $\f) is computed as follows: - * \f[ - * CH\_{ID} = B\_{ID} \times 100 + CH\_{B} - * \f] - * - * Where: - * - \f$ B\_{ID} \f$ is the fragment ID retrieved from `fboard_id_list` based on the slot. - * - \f$ CH\_B \f$ is the channel number on that board. - * - * @return A unique identifier for the specified channel as an unsigned integer. - */ -unsigned int sbndaq::SBNDXARAPUCADecoder::get_channel_id(unsigned int board, unsigned int board_channel) { - unsigned int channel_id = fboard_id_list[board] * 100 + board_channel; - return channel_id; -} +// ==================== Auxiliary functions ==================== // /** * @brief Returns the signed difference between two timestamps (t1 - t2). diff --git a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl index 774032157..d1ac9b9d1 100644 --- a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl +++ b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl @@ -36,12 +36,13 @@ xarapucadecoder: # - Debug options. debug_tdc_handle: false # (De)activates SPEC-TDC art::Handle information printing. debug_ptb_handle: false # (De)activates PTB art::Handle information printing. - debug_fragments_handle: true # (De)activates V1740B CAEN fragments art::Handle information printing. - debug_timing: true # (De)activates timing data printing. + debug_fragments_handle: false # (De)activates V1740B CAEN fragments art::Handle information printing. + debug_timing: false # (De)activates timing data printing. debug_buffer: false # (De)activates buffer status printing. debug_waveforms: false # (De)activates waveforms decoding printing. + debug_extended_fragments: false # (De)activates extended fragments information printing. # - Verbose option. - verbose: true # (De)activates verbosity. + verbose: false # (De)activates verbosity. } END_PROLOG \ No newline at end of file From 60036c5b1117102af1cbc02941a7acd790ae6484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Wed, 15 Oct 2025 06:19:56 -0500 Subject: [PATCH 08/75] Update SBN Document for reference --- sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index 7c46afb10..687818fae 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -10,7 +10,7 @@ * @brief Defines and implements the SBNDXARAPUCADecoder class which inherits from an art::EDProducer * as the decoder for V1740B digitizers, intended for the X-ARAPUCAs. * @details The current version of the SBND X-ARAPUCAs decoder implements the updates shown in - * the SBN Document 38475-v1 in the SBN Document Database. + * the SBN Document 43891-v1 in the SBN Document Database. * @note A Python version of the binary decoding is available for testing purposes. You can find * it [here: V1740 binary decoder](https://github.com/aliciavr/V1740_binary_decoder). */ From 2f7ff4598d720d713fc8c6c662407576efb2117a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Wed, 5 Nov 2025 04:13:09 -0600 Subject: [PATCH 09/75] Add version number and update number of debug waveforms to 0 --- sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc | 1 + sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index 687818fae..321f8db04 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -13,6 +13,7 @@ * the SBN Document 43891-v1 in the SBN Document Database. * @note A Python version of the binary decoding is available for testing purposes. You can find * it [here: V1740 binary decoder](https://github.com/aliciavr/V1740_binary_decoder). + * @version 4.0 */ #include "art/Framework/Core/EDProducer.h" diff --git a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl index d1ac9b9d1..eed2269a9 100644 --- a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl +++ b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl @@ -32,7 +32,7 @@ xarapucadecoder: # - Output data product instance name. waveforms_instance_name: "XARAPUCAChannels" # Name for the instance product containing the raw decoded waveforms. timing_ref_instance_name: "" # Name for the instance product containing the timing reference information. - store_debug_waveforms: -1 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). + store_debug_waveforms: 0 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). # - Debug options. debug_tdc_handle: false # (De)activates SPEC-TDC art::Handle information printing. debug_ptb_handle: false # (De)activates PTB art::Handle information printing. From 15f34cdb45ef5ffb6065bd4973962d9fc3811166 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Thu, 6 Nov 2025 03:46:39 -0600 Subject: [PATCH 10/75] First version of timing check implemented (some extended fragments do not fulfill the requirements --- .../XARAPUCA/SBNDXARAPUCADecoder_module.cc | 56 ++++++++++++++----- .../Decoders/XARAPUCA/xarapucadecoder.fcl | 2 +- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index 321f8db04..7115b0473 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -135,7 +135,7 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { bool fverbose; /**< If `true` it increases verbosity of console output for detailed processing steps. */ // Main processing method. - void decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one); + void decode_fragment(int32_t& prev_TTT, uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one); // Timing. void shift_time(uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t frag_timestamp, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp); @@ -320,6 +320,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { } int32_t nominal_TTT = TTT_DEFAULT; + int32_t prev_TTT = TTT_DEFAULT; uint64_t nominal_frag_timestamp = TTT_DEFAULT; bool last_one = false; @@ -360,7 +361,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { for (size_t f = 0; f < num_caen_fragments; f++) { const artdaq::Fragment fragment = *container_fragment[f].get(); last_one = f == (num_caen_fragments - 1); - decode_fragment(timestamp, nominal_frag_timestamp, nominal_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); + decode_fragment(prev_TTT, timestamp, nominal_frag_timestamp, nominal_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); } // End CAEN V1740 fragments loop. } } // End Container fragments loop. @@ -373,7 +374,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { for (size_t f = 0; f < frag_handle_size; f++) { const artdaq::Fragment fragment = fragment_handle->at(f); last_one = f == (frag_handle_size - 1); - decode_fragment(timestamp, nominal_frag_timestamp, nominal_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); + decode_fragment(prev_TTT, timestamp, nominal_frag_timestamp, nominal_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); } // End CAEN V1740 fragments loop. } } // End extracting CAEN V1740 fragments. @@ -425,7 +426,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { * @see dump_waveforms */ -void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one) { +void sbndaq::SBNDXARAPUCADecoder::decode_fragment(int32_t& prev_TTT, uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one) { auto fragment_id = fragment.fragmentID() - ffragment_id_offset; auto it = std::find(fboard_id_list.begin(), fboard_id_list.end(), fragment_id); size_t board_idx; @@ -445,12 +446,6 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& if (valid_fragment) { if (fverbose) std::cout << "\n > SBNDXARAPUCADecoder::decode_fragment: decoding V1740 CAEN fragment " << fragment_indices[board_idx] << " from the board " << board_idx << " (slot " << fboard_id_list[board_idx] << "):" << std::endl; - bool is_nominal_length = false; - bool is_first = false; - - double ini_wvfm_timestamp = 0; - double end_wvfm_timestamp = 0; - // =============== Accesses Event metadata and Event header for this fragment =============== // CAENV1740Fragment caen_fragment(fragment); @@ -508,13 +503,30 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& std::vector > fragment_wvfms(num_channels, std::vector(num_samples_per_wvfm, 0)); decode_waveforms(fragment, fragment_wvfms, header_size, num_channels, num_samples_per_wvfm, num_words_per_wvfms, num_samples_per_group); - is_nominal_length = (num_nominal_samples_per_wvfm == num_samples_per_wvfm); - is_first = (fragment_indices[board_idx] == 0); + double ini_wvfm_timestamp = 0; + double end_wvfm_timestamp = 0; + + bool is_nominal_length = (num_nominal_samples_per_wvfm == num_samples_per_wvfm); + bool is_first = (fragment_indices[board_idx] == 0); + + int32_t TTT_dif = 0; + // If the fragment timestamp is greater than the TTT end timestamp, it means that rollover occurred. + if (nominal_TTT > TTT_end_ns) { + if (fverbose | fdebug_timing) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN TTT rollover occurred." << std::endl; + TTT_dif = nominal_TTT - (NANOSEC_IN_SEC - TTT_end_ns); + } else { + TTT_dif = TTT_end_ns - nominal_TTT; + } + bool is_in_time = TTT_dif <= static_cast(num_nominal_samples_per_wvfm * fns_per_sample); if (fverbose) { std::cout << " > SBNDXARAPUCADecoder::decode_fragment: processing the decoded fragment and combines the extended ones to their nominal ones if needed." << std::endl; } if (is_nominal_length) { + ///// + int32_t TTT_ini_ns = TTT_end_ns - static_cast(num_nominal_samples_per_wvfm * fns_per_sample); + std::cout << "\t\t NOMINAL fragment (" << num_samples_per_wvfm << "), [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_end_ns - prev_TTT << " ns, length: " << num_samples_per_wvfm * fns_per_sample << " ns, diff_with_length: " << (TTT_end_ns - prev_TTT) - (num_samples_per_wvfm * fns_per_sample) << std::endl; + ////// if (!is_first) { if (fdebug_extended_fragments) { std::cout << "\t\t NOT FIRST NOMINAL fragment " << std::endl; @@ -529,9 +541,23 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& combine_waveforms(wvfms, fragment_wvfms, num_channels); nominal_TTT = TTT_end_ns; nominal_frag_timestamp = frag_timestamp; - } else { - if (fdebug_extended_fragments) std::cout << "\t\t EXTENDED fragment " << std::endl; + } else if (is_in_time) { + if (fdebug_extended_fragments) { + std::cout << "\t\t EXTENDED fragment " << std::endl; + std::cout << "\t\t TTT_dif w.r.t. nominal TTT: " << TTT_dif << " ns, is_in_time: " << is_in_time << std::endl; + } + ///// + int32_t TTT_ini_ns = TTT_end_ns - static_cast(num_nominal_samples_per_wvfm * fns_per_sample); + std::cout << "\t\t EXTENDED fragment (" << num_samples_per_wvfm << "), [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_end_ns - prev_TTT << " ns, length: " << num_samples_per_wvfm * fns_per_sample << " ns, diff_with_length: " << (TTT_end_ns - prev_TTT) - (num_samples_per_wvfm * fns_per_sample) << std::endl; + ////// combine_waveforms(wvfms, fragment_wvfms, num_channels); + } else if (!is_in_time) { + //combine_waveforms(wvfms, fragment_wvfms, num_channels); //TEMP!!!!! + ///// + int32_t TTT_ini_ns = TTT_end_ns - static_cast(num_nominal_samples_per_wvfm * fns_per_sample); + std::cout << "\t\t EXTENDED? fragment (" << num_samples_per_wvfm << "), [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_end_ns - prev_TTT << " ns, length: " << num_samples_per_wvfm * fns_per_sample << " ns, diff_with_length: " << (TTT_end_ns - prev_TTT) - (num_samples_per_wvfm * fns_per_sample) << std::endl; + ////// + std::cout << "\t\t WARNING: EXTENDED fragment out of time window! TTT_dif: " << TTT_dif << " ns, fragment idx: " << fragment_indices[board_idx] << ", board idx: " << board_idx << " (slot " << fboard_id_list[board_idx] << "), " << num_samples_per_wvfm << " samples. Skipping this fragment..." << std::endl; } fragment_indices[board_idx]++; @@ -541,7 +567,9 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& shift_time(TTT_ticks, nominal_TTT, nominal_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); } + prev_TTT = TTT_end_ns; } + } // =============== Timing functions =============== // diff --git a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl index eed2269a9..d1ac9b9d1 100644 --- a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl +++ b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl @@ -32,7 +32,7 @@ xarapucadecoder: # - Output data product instance name. waveforms_instance_name: "XARAPUCAChannels" # Name for the instance product containing the raw decoded waveforms. timing_ref_instance_name: "" # Name for the instance product containing the timing reference information. - store_debug_waveforms: 0 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). + store_debug_waveforms: -1 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). # - Debug options. debug_tdc_handle: false # (De)activates SPEC-TDC art::Handle information printing. debug_ptb_handle: false # (De)activates PTB art::Handle information printing. From 3f44697e583b0dda842ab72e767045551dbac086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Fri, 7 Nov 2025 09:43:44 -0600 Subject: [PATCH 11/75] Add jittering debug option and combine fragments option --- .../XARAPUCA/SBNDXARAPUCADecoder_module.cc | 127 ++++++++++-------- .../Decoders/XARAPUCA/xarapucadecoder.fcl | 7 +- 2 files changed, 76 insertions(+), 58 deletions(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index 7115b0473..fce201a35 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -125,6 +125,8 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { art::ServiceHandle tfs; /**< ServiceHandle object to store the histograms in the decoder_hist.root output file. */ int fstore_debug_waveforms; /**< Number of waveforms to store in the ServiceHandle object for debugging purposes (0: none, -1: all, n: first n waveforms each event). */ + bool fcombine_ext_frag; /**< If `true` combines extended fragments into a single raw::OpDetWaveform object. */ + bool fdebug_tdc_handle; /**< If `true` SPEC-TDC information is printed. */ bool fdebug_ptb_handle; /**< If `true` PTB information is printed. */ bool fdebug_fragments_handle; /**< If `true` V1740B CAEN fragments art::Handle information is printed. */ @@ -132,10 +134,11 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { bool fdebug_buffer; /**< If `true` the buffer status is printed. */ bool fdebug_waveforms; /**< If `true` waveforms decoding data is printed. */ bool fdebug_extended_fragments; /**< If `true` extended fragments information is printed. */ + bool fdebug_jittering; /**< If `true` trigger jittering information is printed. */ bool fverbose; /**< If `true` it increases verbosity of console output for detailed processing steps. */ // Main processing method. - void decode_fragment(int32_t& prev_TTT, uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one); + void decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, int32_t& prev_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one); // Timing. void shift_time(uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t frag_timestamp, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp); @@ -212,6 +215,9 @@ sbndaq::SBNDXARAPUCADecoder::SBNDXARAPUCADecoder(fhicl::ParameterSet const& p) // Gets the number of waveforms to store in the debug output file. fstore_debug_waveforms = p.get ("store_debug_waveforms", 0); + // Gets the combination of extended fragments option. + fcombine_ext_frag = p.get ("combine_ext_frag", true); + // Gets the debug and verbose options. fdebug_ptb_handle = p.get ("debug_ptb_handle", false); fdebug_tdc_handle = p.get ("debug_tdc_handle", false); @@ -219,6 +225,7 @@ sbndaq::SBNDXARAPUCADecoder::SBNDXARAPUCADecoder(fhicl::ParameterSet const& p) fdebug_timing = p.get ("debug_timing", false); fdebug_waveforms = p.get ("debug_waveforms", false); fdebug_extended_fragments = p.get ("debug_extended_fragments", false); + fdebug_jittering = p.get ("debug_jittering", false); fdebug_buffer = p.get ("debug_buffer", false); fverbose = p.get ("verbose", false); @@ -320,7 +327,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { } int32_t nominal_TTT = TTT_DEFAULT; - int32_t prev_TTT = TTT_DEFAULT; + int32_t prev_TTT = 0; uint64_t nominal_frag_timestamp = TTT_DEFAULT; bool last_one = false; @@ -361,7 +368,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { for (size_t f = 0; f < num_caen_fragments; f++) { const artdaq::Fragment fragment = *container_fragment[f].get(); last_one = f == (num_caen_fragments - 1); - decode_fragment(prev_TTT, timestamp, nominal_frag_timestamp, nominal_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); + decode_fragment(timestamp, nominal_frag_timestamp, nominal_TTT, prev_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); } // End CAEN V1740 fragments loop. } } // End Container fragments loop. @@ -374,7 +381,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { for (size_t f = 0; f < frag_handle_size; f++) { const artdaq::Fragment fragment = fragment_handle->at(f); last_one = f == (frag_handle_size - 1); - decode_fragment(prev_TTT, timestamp, nominal_frag_timestamp, nominal_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); + decode_fragment(timestamp, nominal_frag_timestamp, nominal_TTT, prev_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); } // End CAEN V1740 fragments loop. } } // End extracting CAEN V1740 fragments. @@ -426,7 +433,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { * @see dump_waveforms */ -void sbndaq::SBNDXARAPUCADecoder::decode_fragment(int32_t& prev_TTT, uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one) { +void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, int32_t& prev_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one) { auto fragment_id = fragment.fragmentID() - ffragment_id_offset; auto it = std::find(fboard_id_list.begin(), fboard_id_list.end(), fragment_id); size_t board_idx; @@ -506,68 +513,76 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(int32_t& prev_TTT, uint64_t ti double ini_wvfm_timestamp = 0; double end_wvfm_timestamp = 0; - bool is_nominal_length = (num_nominal_samples_per_wvfm == num_samples_per_wvfm); - bool is_first = (fragment_indices[board_idx] == 0); - - int32_t TTT_dif = 0; - // If the fragment timestamp is greater than the TTT end timestamp, it means that rollover occurred. - if (nominal_TTT > TTT_end_ns) { - if (fverbose | fdebug_timing) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN TTT rollover occurred." << std::endl; - TTT_dif = nominal_TTT - (NANOSEC_IN_SEC - TTT_end_ns); - } else { - TTT_dif = TTT_end_ns - nominal_TTT; - } - bool is_in_time = TTT_dif <= static_cast(num_nominal_samples_per_wvfm * fns_per_sample); - if (fverbose) { std::cout << " > SBNDXARAPUCADecoder::decode_fragment: processing the decoded fragment and combines the extended ones to their nominal ones if needed." << std::endl; } - if (is_nominal_length) { - ///// + + if (fcombine_ext_frag) { + bool is_nominal_length = (num_nominal_samples_per_wvfm == num_samples_per_wvfm); + bool is_first = (fragment_indices[board_idx] == 0); + + int32_t TTT_dif = 0; + // If the fragment timestamp is greater than the TTT end timestamp, it means that rollover occurred. + if (nominal_TTT > TTT_end_ns) { + if (fverbose | fdebug_timing) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN TTT rollover occurred." << std::endl; + TTT_dif = nominal_TTT - (NANOSEC_IN_SEC - TTT_end_ns); + } else { + TTT_dif = TTT_end_ns - nominal_TTT; + } + bool is_in_time = TTT_dif <= static_cast(num_nominal_samples_per_wvfm * fns_per_sample); + int32_t TTT_ini_ns = TTT_end_ns - static_cast(num_nominal_samples_per_wvfm * fns_per_sample); - std::cout << "\t\t NOMINAL fragment (" << num_samples_per_wvfm << "), [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_end_ns - prev_TTT << " ns, length: " << num_samples_per_wvfm * fns_per_sample << " ns, diff_with_length: " << (TTT_end_ns - prev_TTT) - (num_samples_per_wvfm * fns_per_sample) << std::endl; - ////// - if (!is_first) { + + if (is_nominal_length) { + if (fdebug_jittering) { + std::cout << "\t\t NOMINAL fragment (" << num_samples_per_wvfm << "), [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_end_ns - prev_TTT << " ns, length: " << num_samples_per_wvfm * fns_per_sample << " ns, diff_with_length: " << (TTT_end_ns - prev_TTT) - (num_samples_per_wvfm * fns_per_sample) << std::endl; + } + if (!is_first) { + if (fdebug_extended_fragments) { + std::cout << "\t\t NOT FIRST NOMINAL fragment " << std::endl; + std::cout << "\t\t nominal_TTT: " << nominal_TTT << " TTT_end_ns: " << TTT_end_ns << std::endl; + std::cout << "\t\t nominal_frag_timestamp: " << nominal_frag_timestamp << " frag_timestamp : " << frag_timestamp << std::endl; + } + shift_time(TTT_ticks, nominal_TTT, nominal_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); + dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); + } else { + if (fdebug_extended_fragments) std::cout << "\t\t FIRST NOMINAL fragment " << std::endl; + } + combine_waveforms(wvfms, fragment_wvfms, num_channels); + nominal_TTT = TTT_end_ns; + nominal_frag_timestamp = frag_timestamp; + } else if (is_in_time) { if (fdebug_extended_fragments) { - std::cout << "\t\t NOT FIRST NOMINAL fragment " << std::endl; - std::cout << "\t\t nominal_TTT: " << nominal_TTT << " TTT_end_ns: " << TTT_end_ns << std::endl; - std::cout << "\t\t nominal_frag_timestamp: " << nominal_frag_timestamp << " frag_timestamp : " << frag_timestamp << std::endl; + std::cout << "\t\t EXTENDED fragment " << std::endl; + std::cout << "\t\t TTT_dif w.r.t. nominal TTT: " << TTT_dif << " ns, is_in_time: " << is_in_time << std::endl; } + if (fdebug_jittering) { + std::cout << "\t\t EXTENDED fragment (" << num_samples_per_wvfm << "), [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_end_ns - prev_TTT << " ns, length: " << num_samples_per_wvfm * fns_per_sample << " ns, diff_with_length: " << (TTT_end_ns - prev_TTT) - (num_samples_per_wvfm * fns_per_sample) << std::endl; + } + + combine_waveforms(wvfms, fragment_wvfms, num_channels); + } else if (!is_in_time) { + //combine_waveforms(wvfms, fragment_wvfms, num_channels); //TEMP!!!!! + if (fdebug_jittering) { + std::cout << "\t\t EXTENDED? fragment (" << num_samples_per_wvfm << "), [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_end_ns - prev_TTT << " ns, length: " << num_samples_per_wvfm * fns_per_sample << " ns, diff_with_length: " << (TTT_end_ns - prev_TTT) - (num_samples_per_wvfm * fns_per_sample) << std::endl; + } + std::cout << "\t\t WARNING: EXTENDED fragment out of time window! TTT_dif: " << TTT_dif << " ns, fragment idx: " << fragment_indices[board_idx] << ", board idx: " << board_idx << " (slot " << fboard_id_list[board_idx] << "), " << num_samples_per_wvfm << " samples. Skipping this fragment..." << std::endl; + } + + fragment_indices[board_idx]++; + + if (last_one) { + if (fdebug_extended_fragments) std::cout << "\t\t LAST fragment " << std::endl; shift_time(TTT_ticks, nominal_TTT, nominal_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); - } else { - if (fdebug_extended_fragments) std::cout << "\t\t FIRST NOMINAL fragment " << std::endl; } - combine_waveforms(wvfms, fragment_wvfms, num_channels); - nominal_TTT = TTT_end_ns; - nominal_frag_timestamp = frag_timestamp; - } else if (is_in_time) { - if (fdebug_extended_fragments) { - std::cout << "\t\t EXTENDED fragment " << std::endl; - std::cout << "\t\t TTT_dif w.r.t. nominal TTT: " << TTT_dif << " ns, is_in_time: " << is_in_time << std::endl; - } - ///// - int32_t TTT_ini_ns = TTT_end_ns - static_cast(num_nominal_samples_per_wvfm * fns_per_sample); - std::cout << "\t\t EXTENDED fragment (" << num_samples_per_wvfm << "), [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_end_ns - prev_TTT << " ns, length: " << num_samples_per_wvfm * fns_per_sample << " ns, diff_with_length: " << (TTT_end_ns - prev_TTT) - (num_samples_per_wvfm * fns_per_sample) << std::endl; - ////// - combine_waveforms(wvfms, fragment_wvfms, num_channels); - } else if (!is_in_time) { - //combine_waveforms(wvfms, fragment_wvfms, num_channels); //TEMP!!!!! - ///// - int32_t TTT_ini_ns = TTT_end_ns - static_cast(num_nominal_samples_per_wvfm * fns_per_sample); - std::cout << "\t\t EXTENDED? fragment (" << num_samples_per_wvfm << "), [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_end_ns - prev_TTT << " ns, length: " << num_samples_per_wvfm * fns_per_sample << " ns, diff_with_length: " << (TTT_end_ns - prev_TTT) - (num_samples_per_wvfm * fns_per_sample) << std::endl; - ////// - std::cout << "\t\t WARNING: EXTENDED fragment out of time window! TTT_dif: " << TTT_dif << " ns, fragment idx: " << fragment_indices[board_idx] << ", board idx: " << board_idx << " (slot " << fboard_id_list[board_idx] << "), " << num_samples_per_wvfm << " samples. Skipping this fragment..." << std::endl; + prev_TTT = TTT_end_ns; + } else { + shift_time(TTT_ticks, TTT_end_ns, frag_timestamp, timestamp, num_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); + dump_waveforms(prod_wvfms, fragment_wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); + fragment_indices[board_idx]++; } - - fragment_indices[board_idx]++; - if (last_one) { - if (fdebug_extended_fragments) std::cout << "\t\t LAST fragment " << std::endl; - shift_time(TTT_ticks, nominal_TTT, nominal_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); - dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); - } - prev_TTT = TTT_end_ns; } } diff --git a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl index d1ac9b9d1..578dba4c8 100644 --- a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl +++ b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl @@ -23,7 +23,7 @@ xarapucadecoder: # - SPEC-TDC access configuration spectdc_product_name: "tdcdecoder" # Name for getting SPEC-TDC Decoder products (if any). spectdc_ftrig_ch: 3 # Channel assigned to flash triggers. - spectdc_etrig_ch: 4 # Channel assigned to ETT (Event Trigger Timestamp) triggers. + spectdc_etrig_ch: 2 # Channel assigned to ETT (Event Trigger Timestamp) triggers. # - PTB access configuration ptb_product_name: "ptbdecoder" # Name for getting PTB Decoder products (if any). allowed_hl_triggers: [1, 2, 3, 4, 5, 14, 15] # List of allowed HLT trigger types (1-5, 14, 15). @@ -32,7 +32,9 @@ xarapucadecoder: # - Output data product instance name. waveforms_instance_name: "XARAPUCAChannels" # Name for the instance product containing the raw decoded waveforms. timing_ref_instance_name: "" # Name for the instance product containing the timing reference information. - store_debug_waveforms: -1 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). + store_debug_waveforms: 0 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). + # Combination of extended fragments. + combine_ext_frag: false # (De)activates the combination of extended fragments into a single raw::OpDetWaveform object. # - Debug options. debug_tdc_handle: false # (De)activates SPEC-TDC art::Handle information printing. debug_ptb_handle: false # (De)activates PTB art::Handle information printing. @@ -41,6 +43,7 @@ xarapucadecoder: debug_buffer: false # (De)activates buffer status printing. debug_waveforms: false # (De)activates waveforms decoding printing. debug_extended_fragments: false # (De)activates extended fragments information printing. + debug_jittering: false # (De)activates trigger jittering information printing. # - Verbose option. verbose: false # (De)activates verbosity. } From 43f761406b187f860d3943471de18d5caaf3ab56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Mon, 24 Nov 2025 11:42:56 -0600 Subject: [PATCH 12/75] Update combination condition with timing features integrating the expected jittering of the extended fragments. --- .../XARAPUCA/SBNDXARAPUCADecoder_module.cc | 137 +++++++++--------- .../Decoders/XARAPUCA/xarapucadecoder.fcl | 11 +- 2 files changed, 78 insertions(+), 70 deletions(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index fce201a35..4922c7da7 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -126,6 +126,7 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { int fstore_debug_waveforms; /**< Number of waveforms to store in the ServiceHandle object for debugging purposes (0: none, -1: all, n: first n waveforms each event). */ bool fcombine_ext_frag; /**< If `true` combines extended fragments into a single raw::OpDetWaveform object. */ + int32_t fallowed_jittering; /**< Allowed jittering (in ns) between fragments to be combined. */ bool fdebug_tdc_handle; /**< If `true` SPEC-TDC information is printed. */ bool fdebug_ptb_handle; /**< If `true` PTB information is printed. */ @@ -138,7 +139,7 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { bool fverbose; /**< If `true` it increases verbosity of console output for detailed processing steps. */ // Main processing method. - void decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, int32_t& prev_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one); + void decode_fragment(uint64_t timestamp, uint64_t& first_frag_timestamp, size_t& first_frag_idx, int32_t& first_TTT, int32_t& prev_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one); // Timing. void shift_time(uint64_t TTT_ticks, int64_t TTT_end_ns, uint64_t frag_timestamp, uint64_t timestamp, uint32_t num_samples_per_wvfm, double& ini_wvfm_timestamp, double& end_wvfm_timestamp); @@ -152,10 +153,10 @@ class sbndaq::SBNDXARAPUCADecoder : public art::EDProducer { unsigned int get_channel_id(unsigned int board, unsigned int board_channel); // Combines decoded waveforms. - void combine_waveforms(std::vector>& wvfms, const std::vector>& fragment_wvfms, uint32_t num_channels); + void append_waveforms(std::vector>& wvfms, const std::vector>& fragment_wvfms, uint32_t num_channels); // Dumps and saves waveforms. - void dump_waveforms(std::vector & prod_wvfms, std::vector>& wvfms, std::vector & fragment_indices, size_t board_index, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp); + void dump_waveforms(std::vector & prod_wvfms, std::vector>& wvfms, size_t first_frag_idx, size_t board_index, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp); void save_prod_wvfm(size_t board_idx, size_t ch, double ini_wvfm_timestamp, const std::vector > & wvfms, std::vector & prod_wvfms); void save_debug_wvfm(size_t board_idx, size_t fragment_idx, int ch, double ini_wvfm_timestamp, double end_wvfm_timestamp, const std::vector > & wvfms); @@ -217,6 +218,7 @@ sbndaq::SBNDXARAPUCADecoder::SBNDXARAPUCADecoder(fhicl::ParameterSet const& p) // Gets the combination of extended fragments option. fcombine_ext_frag = p.get ("combine_ext_frag", true); + fallowed_jittering = p.get ("allowed_jittering", 64); // Gets the debug and verbose options. fdebug_ptb_handle = p.get ("debug_ptb_handle", false); @@ -320,15 +322,16 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { // Flag to track if valid CAEN fragments are found. bool found_caen = false; - std::vector fragment_indices(fnum_caen_boards, 0); + std::vector fragment_indices(fnum_caen_boards, -1); std::vector> wvfms; if (fdebug_extended_fragments) { std::cout << " Waveforms size: " << wvfms.size() << std::endl; } - int32_t nominal_TTT = TTT_DEFAULT; + size_t first_frag_idx = 0; + int32_t first_TTT = TTT_DEFAULT; int32_t prev_TTT = 0; - uint64_t nominal_frag_timestamp = TTT_DEFAULT; + uint64_t first_frag_timestamp = TTT_DEFAULT; bool last_one = false; if (fverbose | fdebug_fragments_handle) std::cout << "\n > SBNDXARAPUCADecoder::produce: searching for V1740 fragments..." << std::endl; @@ -368,7 +371,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { for (size_t f = 0; f < num_caen_fragments; f++) { const artdaq::Fragment fragment = *container_fragment[f].get(); last_one = f == (num_caen_fragments - 1); - decode_fragment(timestamp, nominal_frag_timestamp, nominal_TTT, prev_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); + decode_fragment(timestamp, first_frag_timestamp, first_frag_idx, first_TTT, prev_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); } // End CAEN V1740 fragments loop. } } // End Container fragments loop. @@ -381,7 +384,7 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { for (size_t f = 0; f < frag_handle_size; f++) { const artdaq::Fragment fragment = fragment_handle->at(f); last_one = f == (frag_handle_size - 1); - decode_fragment(timestamp, nominal_frag_timestamp, nominal_TTT, prev_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); + decode_fragment(timestamp, first_frag_timestamp, first_frag_idx, first_TTT, prev_TTT, fragment_indices, fragment, *prod_wvfms, wvfms, last_one); } // End CAEN V1740 fragments loop. } } // End extracting CAEN V1740 fragments. @@ -407,8 +410,9 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { /** * @brief Decodes a CAEN V1740 fragment, extracts the waveforms and combines them into the output product. * @param[in] timestamp The valid timestamp used as reference for the event. - * @param[in,out] nominal_frag_timestamp The nominal timestamp calculated for the fragment being processed. - * @param[in,out] nominal_TTT The nominal Trigger Time Tag (TTT) calculated for the fragment being processed. + * @param[in,out] first_frag_timestamp The nominal timestamp calculated for the fragment being processed. + * @param[in, out] first_frag_idx The first index of the fragments being combined. + * @param[in,out] first_TTT The nominal Trigger Time Tag (TTT) calculated for the fragment being processed. * @param[in,out] fragment_indices A vector containing the indices of the fragments already processed for each board. * @param[in] fragment The artdaq::Fragment object to be processed. * @param[in,out] prod_wvfms The vector of raw::OpDetWaveform objects to be filled with the decoded waveforms. @@ -429,11 +433,11 @@ void sbndaq::SBNDXARAPUCADecoder::produce(art::Event& e) { * @post The vector of raw::OpDetWaveform objects is filled with the decoded waveforms from the fragment. * @see shift_time * @see decode_waveforms - * @see combine_waveforms + * @see append_waveforms * @see dump_waveforms */ -void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& nominal_frag_timestamp, int32_t& nominal_TTT, int32_t& prev_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one) { +void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& first_frag_timestamp, size_t& first_frag_idx, int32_t& first_TTT, int32_t& prev_TTT, std::vector & fragment_indices, const artdaq::Fragment& fragment, std::vector & prod_wvfms, std::vector>& wvfms, bool last_one) { auto fragment_id = fragment.fragmentID() - ffragment_id_offset; auto it = std::find(fboard_id_list.begin(), fboard_id_list.end(), fragment_id); size_t board_idx; @@ -451,6 +455,7 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& } if (valid_fragment) { + fragment_indices[board_idx]++; if (fverbose) std::cout << "\n > SBNDXARAPUCADecoder::decode_fragment: decoding V1740 CAEN fragment " << fragment_indices[board_idx] << " from the board " << board_idx << " (slot " << fboard_id_list[board_idx] << "):" << std::endl; // =============== Accesses Event metadata and Event header for this fragment =============== // @@ -518,71 +523,72 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& } if (fcombine_ext_frag) { - bool is_nominal_length = (num_nominal_samples_per_wvfm == num_samples_per_wvfm); + + // Combination variables and checks. + + bool is_nominal = (num_nominal_samples_per_wvfm == num_samples_per_wvfm); bool is_first = (fragment_indices[board_idx] == 0); + int32_t frag_length = num_samples_per_wvfm * fns_per_sample; // ns. + + // - Computation of the difference w.r.t. previous TTT difference. int32_t TTT_dif = 0; - // If the fragment timestamp is greater than the TTT end timestamp, it means that rollover occurred. - if (nominal_TTT > TTT_end_ns) { + if (prev_TTT > TTT_end_ns) { if (fverbose | fdebug_timing) std::cout << " > SBNDXARAPUCADecoder::decode_fragment: CAEN TTT rollover occurred." << std::endl; - TTT_dif = nominal_TTT - (NANOSEC_IN_SEC - TTT_end_ns); + TTT_dif = prev_TTT - (NANOSEC_IN_SEC - TTT_end_ns); } else { - TTT_dif = TTT_end_ns - nominal_TTT; + TTT_dif = TTT_end_ns - prev_TTT; } - bool is_in_time = TTT_dif <= static_cast(num_nominal_samples_per_wvfm * fns_per_sample); - - int32_t TTT_ini_ns = TTT_end_ns - static_cast(num_nominal_samples_per_wvfm * fns_per_sample); - - if (is_nominal_length) { - if (fdebug_jittering) { - std::cout << "\t\t NOMINAL fragment (" << num_samples_per_wvfm << "), [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_end_ns - prev_TTT << " ns, length: " << num_samples_per_wvfm * fns_per_sample << " ns, diff_with_length: " << (TTT_end_ns - prev_TTT) - (num_samples_per_wvfm * fns_per_sample) << std::endl; - } - if (!is_first) { - if (fdebug_extended_fragments) { - std::cout << "\t\t NOT FIRST NOMINAL fragment " << std::endl; - std::cout << "\t\t nominal_TTT: " << nominal_TTT << " TTT_end_ns: " << TTT_end_ns << std::endl; - std::cout << "\t\t nominal_frag_timestamp: " << nominal_frag_timestamp << " frag_timestamp : " << frag_timestamp << std::endl; + + // - Computation of the difference between TTTs difference and the length of the fragment in ns (to detect jittering between fragments). + //int32_t J = TTT_dif - frag_length; + + // - Combination boolean variable. + //bool dump_comb_wvfms = true; + /* if (is_nominal) { // Nominal fragment + if (!is_first && (TTT_dif <= (frag_length - fallowed_jittering))) { + std::cout << "\t\t WARNING: NOMINAL fragment too close to previous one! TTT_dif: " << TTT_dif << " ns, fragment idx: " << fragment_indices[board_idx] << ", board idx: " << board_idx << " (slot " << fboard_id_list[board_idx] << "), " << num_samples_per_wvfm << " samples. Skipping this fragment..." << std::endl; } - shift_time(TTT_ticks, nominal_TTT, nominal_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); - dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); - } else { - if (fdebug_extended_fragments) std::cout << "\t\t FIRST NOMINAL fragment " << std::endl; - } - combine_waveforms(wvfms, fragment_wvfms, num_channels); - nominal_TTT = TTT_end_ns; - nominal_frag_timestamp = frag_timestamp; - } else if (is_in_time) { - if (fdebug_extended_fragments) { - std::cout << "\t\t EXTENDED fragment " << std::endl; - std::cout << "\t\t TTT_dif w.r.t. nominal TTT: " << TTT_dif << " ns, is_in_time: " << is_in_time << std::endl; - } - if (fdebug_jittering) { - std::cout << "\t\t EXTENDED fragment (" << num_samples_per_wvfm << "), [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_end_ns - prev_TTT << " ns, length: " << num_samples_per_wvfm * fns_per_sample << " ns, diff_with_length: " << (TTT_end_ns - prev_TTT) - (num_samples_per_wvfm * fns_per_sample) << std::endl; - } + } else { // Extended fragment + if (std::abs(J) <= fallowed_jittering) { + dump_comb_wvfms = false; + } else if (TTT_dif <= (frag_length - fallowed_jittering)) { + dump_comb_wvfms = false; + std::cout << "\t\t WARNING: EXTENDED fragment too close to previous one! TTT_dif: " << TTT_dif << " ns, fragment idx: " << fragment_indices[board_idx] << ", board idx: " << board_idx << " (slot " << fboard_id_list[board_idx] << "), " << num_samples_per_wvfm << " samples. Skipping this fragment..." << std::endl; + } + }*/ - combine_waveforms(wvfms, fragment_wvfms, num_channels); - } else if (!is_in_time) { - //combine_waveforms(wvfms, fragment_wvfms, num_channels); //TEMP!!!!! - if (fdebug_jittering) { - std::cout << "\t\t EXTENDED? fragment (" << num_samples_per_wvfm << "), [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_end_ns - prev_TTT << " ns, length: " << num_samples_per_wvfm * fns_per_sample << " ns, diff_with_length: " << (TTT_end_ns - prev_TTT) - (num_samples_per_wvfm * fns_per_sample) << std::endl; - } - std::cout << "\t\t WARNING: EXTENDED fragment out of time window! TTT_dif: " << TTT_dif << " ns, fragment idx: " << fragment_indices[board_idx] << ", board idx: " << board_idx << " (slot " << fboard_id_list[board_idx] << "), " << num_samples_per_wvfm << " samples. Skipping this fragment..." << std::endl; + + bool dump_comb_wvfms = !is_first && (is_nominal || (!is_nominal && (TTT_dif > (frag_length + fallowed_jittering)))); + + if (is_first) { + first_frag_idx = fragment_indices[board_idx]; + first_TTT = TTT_end_ns; + first_frag_timestamp = frag_timestamp; } - - fragment_indices[board_idx]++; + if (dump_comb_wvfms) { + shift_time(TTT_ticks, first_TTT, first_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); + dump_waveforms(prod_wvfms, wvfms, first_frag_idx, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); + first_frag_idx = fragment_indices[board_idx]; + first_TTT = TTT_end_ns; + first_frag_timestamp = frag_timestamp; + } + append_waveforms(wvfms, fragment_wvfms, num_channels); + if (last_one) { if (fdebug_extended_fragments) std::cout << "\t\t LAST fragment " << std::endl; - shift_time(TTT_ticks, nominal_TTT, nominal_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); - dump_waveforms(prod_wvfms, wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); + fragment_indices[board_idx]++; + shift_time(TTT_ticks, first_TTT, first_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); + dump_waveforms(prod_wvfms, wvfms, first_frag_idx, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); } + prev_TTT = TTT_end_ns; - } else { + + } else { // Combination of extended fragments disabled. shift_time(TTT_ticks, TTT_end_ns, frag_timestamp, timestamp, num_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); - dump_waveforms(prod_wvfms, fragment_wvfms, fragment_indices, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); - fragment_indices[board_idx]++; + dump_waveforms(prod_wvfms, fragment_wvfms, first_frag_idx, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); } - } } @@ -1008,8 +1014,8 @@ unsigned int sbndaq::SBNDXARAPUCADecoder::get_channel_id(unsigned int board, uns * @pre The `fragment_wvfms` vector should contain waveforms for all channels of the board being processed. * @pre The `wvfms` vector should be either empty or already contain waveforms for all channels of the board being processed. */ -void sbndaq::SBNDXARAPUCADecoder::combine_waveforms(std::vector>& wvfms, const std::vector>& fragment_wvfms, uint32_t num_channels) { - if (fdebug_extended_fragments) std::cout << " > SBNDXARAPUCADecoder::combine_waveforms: combining waveforms from extended fragments..." << std::endl; +void sbndaq::SBNDXARAPUCADecoder::append_waveforms(std::vector>& wvfms, const std::vector>& fragment_wvfms, uint32_t num_channels) { + if (fdebug_extended_fragments) std::cout << " > SBNDXARAPUCADecoder::append_waveforms: combining waveforms from extended fragments..." << std::endl; if (wvfms.empty()) { if (fdebug_extended_fragments) { std::cout << "\t\t Empty waveforms, resizing to " << num_channels << " channels." << std::endl; @@ -1059,7 +1065,7 @@ void sbndaq::SBNDXARAPUCADecoder::combine_waveforms(std::vector & prod_wvfms, std::vector>& wvfms, std::vector & fragment_indices, size_t board_idx, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp) { +void sbndaq::SBNDXARAPUCADecoder::dump_waveforms(std::vector & prod_wvfms, std::vector>& wvfms, size_t first_frag_idx, size_t board_idx, uint32_t num_channels, double ini_wvfm_timestamp, double end_wvfm_timestamp) { // The decoded waveforms are dumped into two products: // - A xarapucadecoder-art.root file with the OpDetWaveforms as the product of this producer for further analysis. @@ -1078,7 +1084,7 @@ void sbndaq::SBNDXARAPUCADecoder::dump_waveforms(std::vector Date: Tue, 25 Nov 2025 05:02:28 -0600 Subject: [PATCH 13/75] Add warning for some unexpected types of fragments and fix fragments indexing. Improve jittering application. --- .../XARAPUCA/SBNDXARAPUCADecoder_module.cc | 44 +++++++++++-------- .../Decoders/XARAPUCA/xarapucadecoder.fcl | 6 +-- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc index 4922c7da7..76d26660a 100644 --- a/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc +++ b/sbndcode/Decoders/XARAPUCA/SBNDXARAPUCADecoder_module.cc @@ -541,23 +541,7 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& } // - Computation of the difference between TTTs difference and the length of the fragment in ns (to detect jittering between fragments). - //int32_t J = TTT_dif - frag_length; - - // - Combination boolean variable. - //bool dump_comb_wvfms = true; - /* if (is_nominal) { // Nominal fragment - if (!is_first && (TTT_dif <= (frag_length - fallowed_jittering))) { - std::cout << "\t\t WARNING: NOMINAL fragment too close to previous one! TTT_dif: " << TTT_dif << " ns, fragment idx: " << fragment_indices[board_idx] << ", board idx: " << board_idx << " (slot " << fboard_id_list[board_idx] << "), " << num_samples_per_wvfm << " samples. Skipping this fragment..." << std::endl; - } - } else { // Extended fragment - if (std::abs(J) <= fallowed_jittering) { - dump_comb_wvfms = false; - } else if (TTT_dif <= (frag_length - fallowed_jittering)) { - dump_comb_wvfms = false; - std::cout << "\t\t WARNING: EXTENDED fragment too close to previous one! TTT_dif: " << TTT_dif << " ns, fragment idx: " << fragment_indices[board_idx] << ", board idx: " << board_idx << " (slot " << fboard_id_list[board_idx] << "), " << num_samples_per_wvfm << " samples. Skipping this fragment..." << std::endl; - } - }*/ - + int32_t J = TTT_dif - frag_length; bool dump_comb_wvfms = !is_first && (is_nominal || (!is_nominal && (TTT_dif > (frag_length + fallowed_jittering)))); @@ -573,19 +557,43 @@ void sbndaq::SBNDXARAPUCADecoder::decode_fragment(uint64_t timestamp, uint64_t& first_frag_idx = fragment_indices[board_idx]; first_TTT = TTT_end_ns; first_frag_timestamp = frag_timestamp; + if (fdebug_jittering) std::cout << "NC - "; + } else { + if (fdebug_jittering) std::cout << "C - "; } append_waveforms(wvfms, fragment_wvfms, num_channels); if (last_one) { if (fdebug_extended_fragments) std::cout << "\t\t LAST fragment " << std::endl; - fragment_indices[board_idx]++; shift_time(TTT_ticks, first_TTT, first_frag_timestamp, timestamp, num_nominal_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); dump_waveforms(prod_wvfms, wvfms, first_frag_idx, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); } + if (fdebug_jittering) { + if (is_first) { + std::cout << "\t\t FIRST "; + } + if (is_nominal) { + int32_t TTT_ini_ns = TTT_end_ns - static_cast(num_nominal_samples_per_wvfm * fns_per_sample); + std::cout << "NOMINAL fragment " << fboard_id_list[board_idx] << " - " << fragment_indices[board_idx] << " (" << num_samples_per_wvfm << "): [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_dif << " ns, length: " << frag_length << " ns, diff_with_length (jitt): " << J << std::endl; + } else { + int32_t TTT_ini_ns = TTT_end_ns - static_cast(num_nominal_samples_per_wvfm * fns_per_sample); + std::cout << "EXTENDED fragment " << fboard_id_list[board_idx] << " - " << fragment_indices[board_idx] << " (" << num_samples_per_wvfm << "): [" << TTT_ini_ns << ", " << TTT_end_ns << "] diff with prev: " << TTT_dif << " ns, length: " << frag_length << " ns, diff_with_length (jitt): " << J << std::endl; + } + } + + // WARNINGS + if (TTT_dif < frag_length - fallowed_jittering) { + if (!is_first) { + if (!is_nominal) std::cout << "\t\t WARNING: EXTENDED fragment too close! This fragment is being combined." << std::endl; + if (is_nominal) std::cout << "\t\t WARNING: NOMINAL fragment too close! This fragment is not being combined." << std::endl; + } + } + prev_TTT = TTT_end_ns; } else { // Combination of extended fragments disabled. + first_frag_idx = fragment_indices[board_idx]; shift_time(TTT_ticks, TTT_end_ns, frag_timestamp, timestamp, num_samples_per_wvfm, ini_wvfm_timestamp, end_wvfm_timestamp); dump_waveforms(prod_wvfms, fragment_wvfms, first_frag_idx, board_idx, num_channels, ini_wvfm_timestamp, end_wvfm_timestamp); } diff --git a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl index d880a853e..adeb66bd8 100644 --- a/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl +++ b/sbndcode/Decoders/XARAPUCA/xarapucadecoder.fcl @@ -32,7 +32,7 @@ xarapucadecoder: # - Output data product instance name. waveforms_instance_name: "XARAPUCAChannels" # Name for the instance product containing the raw decoded waveforms. timing_ref_instance_name: "" # Name for the instance product containing the timing reference information. - store_debug_waveforms: -1 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). + store_debug_waveforms: 0 # Number of waveforms to store (0: none, -1: all, n: first n waveforms). # Combination of extended fragments. combine_ext_frag: true # (De)activates the combination of extended fragments into a single raw::OpDetWaveform object. allowed_jittering: 64 # Allowed jittering (in ns) between fragments to be combined. @@ -44,9 +44,9 @@ xarapucadecoder: debug_buffer: false # (De)activates buffer status printing. debug_waveforms: false # (De)activates waveforms decoding printing. debug_extended_fragments: false # (De)activates extended fragments information printing. - debug_jittering: true # (De)activates trigger jittering information printing. + debug_jittering: false # (De)activates trigger jittering information printing. # - Verbose option. - verbose: true # (De)activates verbosity. + verbose: false # (De)activates verbosity. } END_PROLOG \ No newline at end of file From 9b056c49c2879a9eff2ff702b88881e60dc5324d Mon Sep 17 00:00:00 2001 From: Lynn Garren Date: Fri, 30 Jan 2026 14:08:34 -0600 Subject: [PATCH 14/75] remove or disable files which reference LegacyLArG4 --- .../LArG4/legacy_largeantmodules_sbnd.fcl | 8 - .../LArG4/legacy_simulationservices_sbnd.fcl | 146 ------------------ 2 files changed, 154 deletions(-) delete mode 100644 sbndcode/LArG4/legacy_largeantmodules_sbnd.fcl delete mode 100644 sbndcode/LArG4/legacy_simulationservices_sbnd.fcl diff --git a/sbndcode/LArG4/legacy_largeantmodules_sbnd.fcl b/sbndcode/LArG4/legacy_largeantmodules_sbnd.fcl deleted file mode 100644 index c6fe393c6..000000000 --- a/sbndcode/LArG4/legacy_largeantmodules_sbnd.fcl +++ /dev/null @@ -1,8 +0,0 @@ -#include "largeantmodules.fcl" - -BEGIN_PROLOG - -sbnd_largeant: @local::standard_largeant -sbnd_largeantana: @local::standard_largeantana - -END_PROLOG diff --git a/sbndcode/LArG4/legacy_simulationservices_sbnd.fcl b/sbndcode/LArG4/legacy_simulationservices_sbnd.fcl deleted file mode 100644 index d359ac6e6..000000000 --- a/sbndcode/LArG4/legacy_simulationservices_sbnd.fcl +++ /dev/null @@ -1,146 +0,0 @@ -# -# File: simulationservices_sbnd.fcl -# Purpose: collection of standard simulation service settings for SBND -# Version: 1.3 -# -# Provides: -# -# - sbnd_g4_services: services needed by LArG4 -# - sbnd_detsim_services: services needed by readout simulation -# - sbnd_simulation_services: bundle of services including Geant4, optical -# and electronics simulation (also includes the core ones) -# -# Use as: -# -# services: { -# @table::sbnd_simulation_services -# # ... -# } -# -# Changes: -# 20160601 (petrillo@fnal.gov) [v1.1] -# content moved from services_sbnd.fcl -# -# 20190807 (dbrailsf@fnal.gov) [v1.2] -# PhotonVisibilityService included in g4 servces table -# OpDetResponseInterface included in detsim services table -# Disabled sbnd_opsimulation_services table -# Enabled 'FastOptical' in the custom physics list (in largeantparameters) -# 20190807 (dbrailsf@fnal.gov) [v1.3] -# Added an optional largeantparameters config which does not run the optical sim -# 20200616 (ascarff@fnal.gov) [v1.4] -# Change diffusion constants to match ProtoDUNE data - - -#include "services_sbnd.fcl" -#include "simulationservices.fcl" -#include "spacecharge_sbnd.fcl" -#include "larfft_sbnd.fcl" -#include "signalservices_sbnd.fcl" -#include "magfield_larsoft.fcl" -#include "particleinventoryservice.fcl" -#include "backtrackerservice.fcl" -#include "spacecharge.fcl" -#include "noiseservices_sbnd.fcl" -#include "photpropservices_sbnd.fcl" - -BEGIN_PROLOG - -sbnd_largeantparameters: @local::standard_largeantparameters # from simulationservices.fcl -sbnd_largeantparameters.ElectronClusterSize: 20.0 -#Brailsford 27/10/09: Enable the custom physics list and disable its neutron killer -sbnd_largeantparameters.UseCustomPhysics: true -sbnd_largeantparameters.EnabledPhysics: [ "Em", "FastOptical", "SynchrotronAndGN", "Ion", "Hadron", "Decay", "HadronElastic", "Stopping" ] #Removed the neutron killer -sbnd_largeantparameters.UseLitePhotons: true -sbnd_largeantparameters.UseModBoxRecomb: false -sbnd_largeantparameters.UseEllipsModBoxRecomb: true - -#Define a largeantparameters which doesn't use the optical simulation -sbnd_largeantparameters_noopticalsim: @local::sbnd_largeantparameters -sbnd_largeantparameters_noopticalsim.EnabledPhysics: [ "Em", "SynchrotronAndGN", "Ion", "Hadron", "Decay", "HadronElastic", "Stopping" ] -sbnd_largeantparameters_noopticalsim.UseModBoxRecomb: false -sbnd_largeantparameters_noopticalsim.UseEllipsModBoxRecomb: true - -# ascarff 16Jun2020: Change the diffusion constants to match ProtoDUNE results -sbnd_largeantparameters.LongitudinalDiffusion: 4.0e-9 #in cm^2/ns (was 6.2e-9) -sbnd_largeantparameters.TransverseDiffusion: 8.8e-9 #in cm^2/ns (was 16.3e-9) -sbnd_largeantparameters_noopticalsim.LongitudinalDiffusion: 4.0e-9 #in cm^2/ns (was 6.2e-9) -sbnd_largeantparameters_noopticalsim.TransverseDiffusion: 8.8e-9 #in cm^2/ns (was 16.3e-9) - -# gputnam 19Aug2024: Add in service configuration without EMB recombination -sbnd_largeantparameters_modbox: @local::sbnd_largeantparameters -sbnd_largeantparameters_modbox.UseModBoxRecomb: true -sbnd_largeantparameters_modbox.UseEllipsModBoxRecomb: false - - -sbnd_larvoxelcalculator: @local::standard_larvoxelcalculator # from simulationservices.fcl - -sbnd_backtrackerservice: @local::standard_backtrackerservice # from backtrackerservice.fcl - -sbnd_backtrackerservice.BackTracker.G4ModuleLabel: "largeant" -sbnd_backtrackerservice.BackTracker.MinimumHitEnergyFraction: 1e-1 -sbnd_backtrackerservice.BackTracker.OverrideRealData: true - -sbnd_particleinventoryservice: @local::standard_particleinventoryservice - -# Define sbnd_g4_services -sbnd_g4_services: -{ - @table::sbnd_services - @table::sbnd_random_services - LArG4Parameters: @local::sbnd_largeantparameters - LArVoxelCalculator: @local::sbnd_larvoxelcalculator - MagneticField: @local::no_mag_larsoft - PhotonVisibilityService: @local::sbnd_Nhits_vuv_vis_prop_timing_photonvisibilityservice -} # sbnd_g4_services - - - -# Define sbnd_detsim_services -sbnd_detsim_services: -{ - @table::sbnd_services - @table::sbnd_random_services - LArFFT: @local::sbnd_larfft - SignalShapingServiceSBND: @local::sbnd_signalshapingservice # from signalservices_sbnd.fcl - NoiseModel: @local::sbnd_uboonedatadrivennoiseservice - OpDetResponseInterface: @local::sbnd_opdetresponse -} # sbnd_detsim_services - - -# Define sbnd_simulation_services -sbnd_simulation_services: -{ - @table::sbnd_services - @table::sbnd_random_services - @table::sbnd_g4_services - @table::sbnd_detsim_services - SignalShapingServiceSBND: @local::sbnd_signalshapingservice # from signalservices_sbnd.fcl - SpaceCharge: @local::sbnd_spacecharge -} - - -#sbnd_opsimulation_services: -#{ -# @table::sbnd_simulation_services -# OpDetResponseInterface: @local::sbnd_opdetresponse -## PhotonVisibilityService: @local::sbnd_photonvisibilityservice -## OpDigiProperties: @local::sbnd_opdigiproperties -#} - - -# Define sbnd_optical_simulation_services -#sbnd_optical_simulation_services.LArPropertiesService.ScintYield: 24000 -#sbnd_optical_simulation_services.LArPropertiesService.EnableCerenkovLight: false -#sbnd_optical_simulation_services.LArG4Parameters.UseCustomPhysics: true -#sbnd_optical_simulation_services.LArG4Parameters.EnabledPhysics: [ "Em", -# "FastOptical", -# "SynchrotronAndGN", -# "Ion", -# "Hadron", -# "Decay", -# "HadronElastic", -# "Stopping", -# "NeutronTrackingCut" ] - -END_PROLOG From 9297360ffcfbabc353a80eac8be354b0e9ea23e3 Mon Sep 17 00:00:00 2001 From: Lynn Garren Date: Fri, 30 Jan 2026 14:08:50 -0600 Subject: [PATCH 15/75] remove or disable files which reference LegacyLArG4 --- sbndcode/JobConfigurations/standard/detsim/CMakeLists.txt | 3 ++- sbndcode/JobConfigurations/standard/g4/CMakeLists.txt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sbndcode/JobConfigurations/standard/detsim/CMakeLists.txt b/sbndcode/JobConfigurations/standard/detsim/CMakeLists.txt index 0b3773a0c..5803f01d3 100644 --- a/sbndcode/JobConfigurations/standard/detsim/CMakeLists.txt +++ b/sbndcode/JobConfigurations/standard/detsim/CMakeLists.txt @@ -4,5 +4,6 @@ FILE(GLOB fcl_files *.fcl) install_source(EXTRAS ${fcl_files} ) add_subdirectory(detector_variations) -add_subdirectory(legacy) +# LegacyLArG4 is not supported when using geant4 4.11 +##add_subdirectory(legacy) diff --git a/sbndcode/JobConfigurations/standard/g4/CMakeLists.txt b/sbndcode/JobConfigurations/standard/g4/CMakeLists.txt index 91660cfa0..a82cc1a6b 100644 --- a/sbndcode/JobConfigurations/standard/g4/CMakeLists.txt +++ b/sbndcode/JobConfigurations/standard/g4/CMakeLists.txt @@ -7,4 +7,5 @@ add_subdirectory(recomb_variations) add_subdirectory(crt_filter) add_subdirectory(optical_sim) -add_subdirectory(legacy) +# LegacyLArG4 is not supported when using geant4 4.11 +##add_subdirectory(legacy) From a531049c055fad69623d5355ad56071d001722d8 Mon Sep 17 00:00:00 2001 From: Lynn Garren Date: Fri, 30 Jan 2026 14:09:03 -0600 Subject: [PATCH 16/75] remove or disable files which reference LegacyLArG4 --- test/fcl/testFHiCLfiles_sbnd.sh | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/test/fcl/testFHiCLfiles_sbnd.sh b/test/fcl/testFHiCLfiles_sbnd.sh index b9eda6ec0..b2f1695a2 100755 --- a/test/fcl/testFHiCLfiles_sbnd.sh +++ b/test/fcl/testFHiCLfiles_sbnd.sh @@ -46,13 +46,14 @@ if [[ -n "$MRB_BUILDDIR" ]]; then fi fi -if [[ -n "$MRB_SOURCE" ]]; then - SourceFHiCLdir="${MRB_SOURCE}/sbndcode/sbndcode/JobConfigurations" - if [[ -d "$SourceFHiCLdir" ]]; then - echo "Will test the job configuration directory in MRB source area ('${SourceFHiCLdir}')" - TestDirs+=( "$SourceFHiCLdir" ) - fi -fi +# DO NOT test files that are not installed +#if [[ -n "$MRB_SOURCE" ]]; then +# SourceFHiCLdir="${MRB_SOURCE}/sbndcode/sbndcode/JobConfigurations" +# if [[ -d "$SourceFHiCLdir" ]]; then +# echo "Will test the job configuration directory in MRB source area ('${SourceFHiCLdir}')" +# TestDirs+=( "$SourceFHiCLdir" ) +# fi +#fi if [[ "${#TestDirs[@]}]" == 0 ]]; then echo "FATAL: no suitable FHiCL directory found to be tested!" >&2 From cc0cd3ac7f7f101f4541a431927622aba24f2fe5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alicia=20V=C3=A1zquez-Ramos?= Date: Tue, 3 Feb 2026 11:21:27 -0600 Subject: [PATCH 17/75] Restore the shower merging algorithm in another place to avoid inconsistent state of PFParticles (-1 track scores). --- .../scripts/PandoraSettings_Neutrino_SBND.xml | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/sbndcode/SBNDPandora/scripts/PandoraSettings_Neutrino_SBND.xml b/sbndcode/SBNDPandora/scripts/PandoraSettings_Neutrino_SBND.xml index 0fb9f13d0..1c177a684 100644 --- a/sbndcode/SBNDPandora/scripts/PandoraSettings_Neutrino_SBND.xml +++ b/sbndcode/SBNDPandora/scripts/PandoraSettings_Neutrino_SBND.xml @@ -447,6 +447,39 @@ TrackParticles3D ShowerParticles3D DaughterVertices3D ClustersU ClustersV ClustersW TrackClusters3D ShowerClusters3D + + + TrackParticles3D ShowerParticles3D + TrackParticles3D ShowerParticles3D DaughterVertices3D ClustersU ClustersV ClustersW TrackClusters3D ShowerClusters3D + + + + + TrackParticles3D + ShowerParticles3D + true + PandoraMVAs/PandoraBdt_SBND.xml + PfoCharBDT2 + PandoraMVAs/PandoraBdt_SBND.xml + PfoCharBDTNoChargeInfo2 + 0.51 + true + + + + + + + + + + + + + + + + NeutrinoParticles3D From 888ecbbaa3c530acc23aafa9e53e17e9a7453936 Mon Sep 17 00:00:00 2001 From: AndyChappell Date: Thu, 5 Feb 2026 02:48:32 -0600 Subject: [PATCH 18/75] Add fcl and pandora xml to support cluster validation metrics in ci system --- .../standard/reco/ci_reco2_sbnd.fcl | 4 ++ .../scripts/PandoraSettings_CI_SBND.xml | 52 +++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 sbndcode/JobConfigurations/standard/reco/ci_reco2_sbnd.fcl create mode 100644 sbndcode/SBNDPandora/scripts/PandoraSettings_CI_SBND.xml diff --git a/sbndcode/JobConfigurations/standard/reco/ci_reco2_sbnd.fcl b/sbndcode/JobConfigurations/standard/reco/ci_reco2_sbnd.fcl new file mode 100644 index 000000000..0ae1c3621 --- /dev/null +++ b/sbndcode/JobConfigurations/standard/reco/ci_reco2_sbnd.fcl @@ -0,0 +1,4 @@ +#include "standard_reco2_sbnd.fcl" + +physics.producers.pandora.ConfigFile: "PandoraSettings_CI_SBND.xml" +physics.producers.pandora.EnableMCParticles: true diff --git a/sbndcode/SBNDPandora/scripts/PandoraSettings_CI_SBND.xml b/sbndcode/SBNDPandora/scripts/PandoraSettings_CI_SBND.xml new file mode 100644 index 000000000..fede0b0e7 --- /dev/null +++ b/sbndcode/SBNDPandora/scripts/PandoraSettings_CI_SBND.xml @@ -0,0 +1,52 @@ + + + true + false + true + + + + CaloHitListU + CaloHitListV + CaloHitListW + CaloHitList2D + CaloHitList2D + + + + PandoraSettings_Cosmic_SBND.xml + PandoraSettings_Neutrino_SBND.xml + PandoraSettings_Slicing_Standard.xml + + true + false + + + + + + + PandoraMVAs/PandoraBdt_SBND.xml + NeutrinoId + 0 + -1 + 999 + true + + + CaloHitList2D + RecreatedPfos + RecreatedClusters + RecreatedVertices + false + + + + ci_pandora_clusters.root + pandora_clusters + RecreatedClusters + CaloHitList2D + 5 + true + + From bcb99eed83a9a0d6bf07bec57747ed0f05119f11 Mon Sep 17 00:00:00 2001 From: AndyChappell Date: Thu, 5 Feb 2026 04:09:42 -0600 Subject: [PATCH 19/75] Add synchronisation comment to Pandora Master xml --- sbndcode/SBNDPandora/scripts/PandoraSettings_Master_SBND.xml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sbndcode/SBNDPandora/scripts/PandoraSettings_Master_SBND.xml b/sbndcode/SBNDPandora/scripts/PandoraSettings_Master_SBND.xml index 93658e987..aefbce4da 100644 --- a/sbndcode/SBNDPandora/scripts/PandoraSettings_Master_SBND.xml +++ b/sbndcode/SBNDPandora/scripts/PandoraSettings_Master_SBND.xml @@ -1,3 +1,7 @@ + false From 542d2f53748ac2646c619e51a8a342b2c54fe9c5 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 3 Apr 2025 11:56:51 -0500 Subject: [PATCH 20/75] Add CRTBlob producer --- sbndcode/CRT/CRTReco/CMakeLists.txt | 6 + .../CRT/CRTReco/CRTBlobProducer_module.cc | 219 ++++++++++++++++++ .../CRT/CRTReco/crtrecoproducers_sbnd.fcl | 11 + 3 files changed, 236 insertions(+) create mode 100644 sbndcode/CRT/CRTReco/CRTBlobProducer_module.cc diff --git a/sbndcode/CRT/CRTReco/CMakeLists.txt b/sbndcode/CRT/CRTReco/CMakeLists.txt index 3ea86c28c..f17015c69 100644 --- a/sbndcode/CRT/CRTReco/CMakeLists.txt +++ b/sbndcode/CRT/CRTReco/CMakeLists.txt @@ -37,4 +37,10 @@ simple_plugin( Eigen3::Eigen ) +simple_plugin( + CRTBlobProducer module + sbnobj::SBND_CRT + sbndcode_GeoWrappers +) + install_fhicl() diff --git a/sbndcode/CRT/CRTReco/CRTBlobProducer_module.cc b/sbndcode/CRT/CRTReco/CRTBlobProducer_module.cc new file mode 100644 index 000000000..0ea91e935 --- /dev/null +++ b/sbndcode/CRT/CRTReco/CRTBlobProducer_module.cc @@ -0,0 +1,219 @@ +//////////////////////////////////////////////////////////////////////// +// Class: CRTBlobProducer +// Plugin Type: producer +// File: CRTBlobProducer_module.cc +// +// Author: Henry Lay (h.lay@sheffield.ac.uk) +//////////////////////////////////////////////////////////////////////// + +#include "art/Framework/Core/EDProducer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" +#include "art/Framework/Principal/SubRun.h" +#include "canvas/Utilities/InputTag.h" +#include "canvas/Persistency/Common/FindOneP.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" + +#include "lardata/Utilities/AssociationUtil.h" + +#include "sbnobj/SBND/CRT/CRTCluster.hh" +#include "sbnobj/SBND/CRT/CRTSpacePoint.hh" +#include "sbnobj/SBND/CRT/CRTBlob.hh" + +#include + +namespace sbnd::crt { + class CRTBlobProducer; +} + +class sbnd::crt::CRTBlobProducer : public art::EDProducer { +public: + explicit CRTBlobProducer(fhicl::ParameterSet const& p); + + CRTBlobProducer(CRTBlobProducer const&) = delete; + CRTBlobProducer(CRTBlobProducer&&) = delete; + CRTBlobProducer& operator=(CRTBlobProducer const&) = delete; + CRTBlobProducer& operator=(CRTBlobProducer&&) = delete; + + void produce(art::Event& e) override; + + void OrderSpacePoints(std::vector> &spacePointVec, const art::FindOneP &spacePointsToCluster); + + std::vector>> CreateBlobCandidates(const std::vector> &spacePointVec, + const art::FindOneP &spacePointsToCluster); + + void TimeErrorCalculator(const std::vector ×, double &mean, double &err); + + void OrderBlobCandidates(std::vector>> &blobCandidates); + + std::vector>> ChoseBlobs(std::vector>> &blobCandidates); + +private: + + std::string fCRTSpacePointModuleLabel; + double fCoincidenceTimeRequirement; + bool fUseTs0; +}; + + +sbnd::crt::CRTBlobProducer::CRTBlobProducer(fhicl::ParameterSet const& p) + : EDProducer{p} + , fCRTSpacePointModuleLabel(p.get("CRTSpacePointModuleLabel")) + , fCoincidenceTimeRequirement(p.get("CoincidenceTimeRequirement")) + , fUseTs0(p.get("UseTs0")) +{ + produces>(); + produces>(); +} + +void sbnd::crt::CRTBlobProducer::produce(art::Event& e) +{ + auto blobVec = std::make_unique>(); + auto blobSpacePointAssn = std::make_unique>(); + + art::Handle> CRTSpacePointHandle; + e.getByLabel(fCRTSpacePointModuleLabel, CRTSpacePointHandle); + + std::vector> CRTSpacePointVec; + art::fill_ptr_vector(CRTSpacePointVec, CRTSpacePointHandle); + + art::FindOneP spacePointsToCluster(CRTSpacePointHandle, e, fCRTSpacePointModuleLabel); + + OrderSpacePoints(CRTSpacePointVec, spacePointsToCluster); + + std::vector>> blobCandidates = CreateBlobCandidates(CRTSpacePointVec, spacePointsToCluster); + + OrderBlobCandidates(blobCandidates); + + std::vector>> chosenBlobs = ChoseBlobs(blobCandidates); + + for(auto const& [blob, spIDs] : chosenBlobs) + { + blobVec->push_back(blob); + + for(auto const& spID : spIDs) + util::CreateAssn(*this, e, *blobVec, CRTSpacePointVec[spID], *blobSpacePointAssn); + } + + e.put(std::move(blobVec)); + e.put(std::move(blobSpacePointAssn)); +} + +void sbnd::crt::CRTBlobProducer::OrderSpacePoints(std::vector> &spacePointVec, const art::FindOneP &spacePointsToCluster) +{ + std::sort(spacePointVec.begin(), spacePointVec.end(), + [&](const art::Ptr &a, const art::Ptr &b) -> bool { + if(fUseTs0) + return a->Ts0() < b->Ts0(); + else + return a->Ts1() < b->Ts1(); + }); +} + +std::vector>> sbnd::crt::CRTBlobProducer::CreateBlobCandidates(const std::vector> &spacePointVec, + const art::FindOneP &spacePointsToCluster) +{ + std::vector>> candidates; + + for(unsigned i = 0; i < spacePointVec.size(); ++i) + { + const art::Ptr primarySpacePoint = spacePointVec[i]; + const art::Ptr primaryCluster = spacePointsToCluster.at(primarySpacePoint.key()); + + std::set used_spacepoints = { i }; + std::vector t0s = { primarySpacePoint->Ts0() }; + std::vector t1s = { primarySpacePoint->Ts1() }; + std::vector pes = { primarySpacePoint->PE() }; + + std::map taggers; + for(int i = 0; i < 7; ++i) + taggers[(CRTTagger)i] = 0; + ++taggers[primaryCluster->Tagger()]; + + for(unsigned ii = i+1; ii < spacePointVec.size(); ++ii) + { + const art::Ptr secondarySpacePoint = spacePointVec[ii]; + const art::Ptr secondaryCluster = spacePointsToCluster.at(secondarySpacePoint.key()); + + const double tdiff_prim_sec = fUseTs0 ? secondarySpacePoint->Ts0() - primarySpacePoint->Ts0() : secondarySpacePoint->Ts1() - primarySpacePoint->Ts1(); + + if(tdiff_prim_sec > fCoincidenceTimeRequirement) + break; + + used_spacepoints.insert(ii); + t0s.push_back(secondarySpacePoint->Ts0()); + t1s.push_back(secondarySpacePoint->Ts1()); + pes.push_back(secondarySpacePoint->PE()); + ++taggers[secondaryCluster->Tagger()]; + } + + double t0, et0; + TimeErrorCalculator(t0s, t0, et0); + + double t1, et1; + TimeErrorCalculator(t1s, t1, et1); + + const double pe = std::accumulate(pes.begin(), pes.end(), 0.); + + const CRTBlob blob(t0, et0, t1, et1, pe, taggers); + + candidates.emplace_back(blob, used_spacepoints); + } + + return candidates; +} + +void sbnd::crt::CRTBlobProducer::TimeErrorCalculator(const std::vector ×, double &mean, double &err) +{ + double sum = 0.; + for(auto const &time : times) + sum += time; + + mean = sum / times.size(); + + double summed_var = 0.; + for(auto const &time : times) + summed_var += std::pow((time - mean), 2); + + err = std::sqrt(summed_var / (times.size() - 1)); +} + +void sbnd::crt::CRTBlobProducer::OrderBlobCandidates(std::vector>> &blobCandidates) +{ + std::sort(blobCandidates.begin(), blobCandidates.end(), + [&](const std::pair> &a, const std::pair> &b) -> bool { + return fUseTs0 ? a.first.Ts0Err() < b.first.Ts0Err() : a.first.Ts1Err() < b.first.Ts1Err(); + }); +} + +std::vector>> sbnd::crt::CRTBlobProducer::ChoseBlobs(std::vector>> &blobCandidates) +{ + std::vector>> chosenBlobs; + + std::set used; + + for(auto const& [blob, spIDs] : blobCandidates) + { + bool keep = true; + for(auto const& spID : spIDs) + { + if(used.count(spID) != 0) + keep = false; + } + + if(keep) + { + chosenBlobs.emplace_back(blob, spIDs); + + for(auto const& spID : spIDs) + used.insert(spID); + } + } + + return chosenBlobs; +} + +DEFINE_ART_MODULE(sbnd::crt::CRTBlobProducer) diff --git a/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl b/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl index 9aa8e2a26..0b4ca1c3c 100644 --- a/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl +++ b/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl @@ -78,4 +78,15 @@ crttrackproducer_data_sbnd: @local::crttrackproducer_sbnd crttrackproducer_data_sbnd.UseTs0: true crttrackproducer_data_sbnd.MaskedTaggers: [ ] +crtblobproducer_sbnd: +{ + CRTSpacePointModuleLabel: "crtspacepoints" + CoincidenceTimeRequirement: 100. + UseTs0: false + module_type: "CRTBlobProducer" +} + +crtblobproducer_data_sbnd: @local::crtblobproducer_sbnd +crtblobproducer_data_sbnd.UseTs0: true + END_PROLOG From 5811843ff090310ea0a9187b259d36d9b9077003 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 3 Apr 2025 11:58:11 -0500 Subject: [PATCH 21/75] Add blobs to CRT only fcls --- sbndcode/CRT/CRTReco/run_crtblobreco.fcl | 38 +++++++++++++++++++++++ sbndcode/CRT/CRTReco/run_crtreco.fcl | 3 +- sbndcode/CRT/CRTReco/run_crtreco_data.fcl | 1 + sbndcode/CRT/CRTReco/run_crtrecoana.fcl | 3 +- 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 sbndcode/CRT/CRTReco/run_crtblobreco.fcl diff --git a/sbndcode/CRT/CRTReco/run_crtblobreco.fcl b/sbndcode/CRT/CRTReco/run_crtblobreco.fcl new file mode 100644 index 000000000..7d46331d2 --- /dev/null +++ b/sbndcode/CRT/CRTReco/run_crtblobreco.fcl @@ -0,0 +1,38 @@ +#include "services_sbnd.fcl" +#include "rootoutput_sbnd.fcl" +#include "crtrecoproducers_sbnd.fcl" + +process_name: CRTBlobReco + +services: +{ + @table::sbnd_services +} + +source: +{ + module_type: RootInput +} + +outputs: +{ + out1: + { + @table::sbnd_rootoutput + dataTier: "reconstructed" + } +} + +physics: +{ + producers: + { + crtblobs: @local::crtblobproducer_sbnd + } + + reco: [ crtblobs ] + stream1: [ out1 ] + + trigger_paths: [ reco ] + end_paths: [ stream1 ] +} diff --git a/sbndcode/CRT/CRTReco/run_crtreco.fcl b/sbndcode/CRT/CRTReco/run_crtreco.fcl index 3a625c1b7..585238a0a 100644 --- a/sbndcode/CRT/CRTReco/run_crtreco.fcl +++ b/sbndcode/CRT/CRTReco/run_crtreco.fcl @@ -33,9 +33,10 @@ physics: crtclustering: @local::crtclusterproducer_sbnd crtspacepoints: @local::crtspacepointproducer_sbnd crttracks: @local::crttrackproducer_sbnd + crtblobs: @local::crtblobproducer_sbnd } - reco: [ crtstrips, crtclustering, crtspacepoints, crttracks ] + reco: [ crtstrips, crtclustering, crtspacepoints, crttracks, crtblobs ] stream1: [ out1 ] trigger_paths: [ reco ] diff --git a/sbndcode/CRT/CRTReco/run_crtreco_data.fcl b/sbndcode/CRT/CRTReco/run_crtreco_data.fcl index 2493c9b33..9e179b108 100644 --- a/sbndcode/CRT/CRTReco/run_crtreco_data.fcl +++ b/sbndcode/CRT/CRTReco/run_crtreco_data.fcl @@ -10,6 +10,7 @@ physics.producers.crtstrips: @local::crtstriphitproducer_data_sbnd physics.producers.crtclustering: @local::crtclusterproducer_data_sbnd physics.producers.crtspacepoints: @local::crtspacepointproducer_data_sbnd physics.producers.crttracks: @local::crttrackproducer_data_sbnd +physics.producers.crtblobs: @local::crtblobproducer_data_sbnd outputs.out1.outputCommands: [ "keep *_*_*_*", "drop *_daq_*_*", diff --git a/sbndcode/CRT/CRTReco/run_crtrecoana.fcl b/sbndcode/CRT/CRTReco/run_crtrecoana.fcl index 983502ca8..6e9f6d8c8 100644 --- a/sbndcode/CRT/CRTReco/run_crtrecoana.fcl +++ b/sbndcode/CRT/CRTReco/run_crtrecoana.fcl @@ -37,6 +37,7 @@ physics: crtclustering: @local::crtclusterproducer_sbnd crtspacepoints: @local::crtspacepointproducer_sbnd crttracks: @local::crttrackproducer_sbnd + crtblobs: @local::crtblobproducer_sbnd } analyzers: @@ -44,7 +45,7 @@ physics: crtana: @local::crtana_sbnd } - reco: [ crtstrips, crtclustering, crtspacepoints, crttracks ] + reco: [ crtstrips, crtclustering, crtspacepoints, crttracks, crtblobs ] ana: [ crtana ] stream1: [ out1 ] From 8dba4972baeb079d312346e1634ce81f96b42a35 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 16 Feb 2026 05:57:59 -0600 Subject: [PATCH 22/75] Modernise CMakeLists --- sbndcode/CRT/CRTReco/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbndcode/CRT/CRTReco/CMakeLists.txt b/sbndcode/CRT/CRTReco/CMakeLists.txt index f17015c69..ad5cfc7cb 100644 --- a/sbndcode/CRT/CRTReco/CMakeLists.txt +++ b/sbndcode/CRT/CRTReco/CMakeLists.txt @@ -39,8 +39,8 @@ simple_plugin( simple_plugin( CRTBlobProducer module + lardata::Utilities sbnobj::SBND_CRT - sbndcode_GeoWrappers ) install_fhicl() From 5cb14c3ed066bdf7e45b1955dd4b48fe97fb2132 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 20 Feb 2025 08:12:04 -0600 Subject: [PATCH 23/75] Change ADC saturation value to match data --- sbndcode/CRT/CRTSimulation/crtsimmodules_sbnd.fcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbndcode/CRT/CRTSimulation/crtsimmodules_sbnd.fcl b/sbndcode/CRT/CRTSimulation/crtsimmodules_sbnd.fcl index 2d9acb68e..ca546268b 100644 --- a/sbndcode/CRT/CRTSimulation/crtsimmodules_sbnd.fcl +++ b/sbndcode/CRT/CRTSimulation/crtsimmodules_sbnd.fcl @@ -58,7 +58,7 @@ standard_sbnd_crtsimparams: { # Minimum time between energy deposits that SiPMs can resolve [ns] SipmTimeResponse: 2.0 - AdcSaturation: 4095 + AdcSaturation: 4089 DeadTime: 22000 From 6220ac49bff507347a458c0b284887e7eb0cac50 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 20 Feb 2025 08:13:41 -0600 Subject: [PATCH 24/75] Use saturation to correctly label strip hits --- sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc | 4 +++- sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc b/sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc index 1f212abd1..fe536a734 100644 --- a/sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc +++ b/sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc @@ -62,6 +62,7 @@ class sbnd::crt::CRTStripHitProducer : public art::EDProducer { std::string fFEBDataModuleLabel; uint16_t fADCThreshold; + uint16_t fADCSaturation; std::vector fErrorCoeff; bool fAllowFlag1; bool fApplyTs0Window; @@ -88,6 +89,7 @@ sbnd::crt::CRTStripHitProducer::CRTStripHitProducer(fhicl::ParameterSet const& p : EDProducer{p} , fFEBDataModuleLabel(p.get("FEBDataModuleLabel")) , fADCThreshold(p.get("ADCThreshold")) + , fADCSaturation(p.get("ADCSaturation")) , fErrorCoeff(p.get>("ErrorCoeff")) , fAllowFlag1(p.get("AllowFlag1")) , fApplyTs0Window(p.get("ApplyTs0Window")) @@ -290,7 +292,7 @@ std::vector sbnd::crt::CRTStripHitProducer::CreateStripH if(pos - err < 0) err = pos; - stripHits.emplace_back(offline_channel_id, t0, t1, ref_time_s, pos, err, adc1, adc2); + stripHits.emplace_back(offline_channel_id, t0, t1, ref_time_s, pos, err, adc1, adc2, fADCSaturation); } } diff --git a/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl b/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl index 9aa8e2a26..2de95131c 100644 --- a/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl +++ b/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl @@ -6,6 +6,7 @@ crtstriphitproducer_sbnd: { FEBDataModuleLabel: "crtsim" ADCThreshold: 60 + ADCSaturation: @local::sbnd_crtsim.DetSimParams.AdcSaturation ErrorCoeff: [ 0.26, -0.27, 0.025 ] AllowFlag1: false ApplyTs0Window: false From ae474af618dae9a371e030e97641d022ebf64ad9 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 17 Feb 2026 10:58:08 -0600 Subject: [PATCH 25/75] Add option for blob branches in CRTAnalysis module --- sbndcode/CRT/CRTAna/CRTAnalysis_module.cc | 78 ++++++++++++++++++++++- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc index 948d3fd4c..29f6614c9 100644 --- a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc @@ -33,6 +33,7 @@ #include "sbnobj/SBND/CRT/CRTCluster.hh" #include "sbnobj/SBND/CRT/CRTSpacePoint.hh" #include "sbnobj/SBND/CRT/CRTTrack.hh" +#include "sbnobj/SBND/CRT/CRTBlob.hh" #include "sbnobj/SBND/Timing/DAQTimestamp.hh" #include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" @@ -87,6 +88,8 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { void AnalyseCRTTracks(const art::Event &e, const std::vector> &CRTTrackVec, const art::FindManyP &tracksToSpacePoints, const art::FindOneP &spacePointsToClusters, const art::FindManyP &clustersToStripHits); + void AnalyseCRTBlobs(std::vector> &CRTBlobVec); + void AnalyseTPCMatching(const art::Event &e, const art::Handle> &TPCTrackHandle, const art::Handle> &CRTSpacePointHandle, const art::Handle> &CRTClusterHandle, const art::Handle> &PFPHandle, @@ -104,10 +107,10 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { CRTBackTrackerAlg fCRTBackTrackerAlg; std::string fMCParticleModuleLabel, fSimDepositModuleLabel, fFEBDataModuleLabel, fCRTStripHitModuleLabel, - fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, fCRTTrackModuleLabel, fTPCTrackModuleLabel, + fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, fCRTTrackModuleLabel, fCRTBlobModuleLabel, fTPCTrackModuleLabel, fCRTSpacePointMatchingModuleLabel, fCRTTrackMatchingModuleLabel, fPFPModuleLabel, fPTBModuleLabel, fTDCModuleLabel, fTimingReferenceModuleLabel; - bool fDebug, fDataMode, fNoTPC, fHasPTB, fHasTDC, fTruthMatch; + bool fDebug, fDataMode, fNoTPC, fHasPTB, fHasTDC, fHasBlobs, fTruthMatch; //! Adding some of the reco parameters to save corrections double fPEAttenuation, fTimeWalkNorm, fTimeWalkScale, fPropDelay; @@ -296,6 +299,16 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _tr_truth_theta; std::vector _tr_truth_phi; + // crt blob information + std::vector _bl_ts0; + std::vector _bl_ets0; + std::vector _bl_ts1; + std::vector _bl_ets1; + std::vector _bl_pe; + std::vector _bl_nsps; + std::vector> _bl_nsps_per_tagger; + + // tpc track information (including crt matching) std::vector _tpc_start_x; std::vector _tpc_start_y; std::vector _tpc_start_z; @@ -341,12 +354,14 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _tpc_tr_end_z; std::vector _tpc_tr_score; + // ptb information (trigger board) std::vector _ptb_hlt_trigger; std::vector _ptb_hlt_timestamp; std::vector _ptb_llt_trigger; std::vector _ptb_llt_timestamp; + // spec tdc information (timing board) std::vector _tdc_channel; std::vector _tdc_timestamp; std::vector _tdc_offset; @@ -364,6 +379,7 @@ sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) fCRTClusterModuleLabel = p.get("CRTClusterModuleLabel", "crtclustering"); fCRTSpacePointModuleLabel = p.get("CRTSpacePointModuleLabel", "crtspacepoints"); fCRTTrackModuleLabel = p.get("CRTTrackModuleLabel", "crttracks"); + fCRTBlobModuleLabel = p.get("CRTBlobModuleLabel", "crtblobs"); fTPCTrackModuleLabel = p.get("TPCTrackModuleLabel", "pandoraSCETrack"); fCRTSpacePointMatchingModuleLabel = p.get("CRTSpacePointMatchingModuleLabel", "crtspacepointmatchingSCE"); fCRTTrackMatchingModuleLabel = p.get("CRTTrackMatchingModuleLabel", "crttrackmatchingSCE"); @@ -376,8 +392,8 @@ sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) fNoTPC = p.get("NoTPC", false); fHasPTB = p.get("HasPTB", false); fHasTDC = p.get("HasTDC", false); + fHasBlobs = p.get("HasBlobs", false); fTruthMatch = p.get("TruthMatch", true); - //! Adding some of the reco parameters to save corrections fPEAttenuation = p.get("PEAttenuation", 1.0); fTimeWalkNorm = p.get("TimeWalkNorm", 0.0); fTimeWalkScale = p.get("TimeWalkScale", 0.0); @@ -578,6 +594,17 @@ sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) fTree->Branch("tr_truth_phi", "std::vector", &_tr_truth_phi); } + if(fHasBlobs) + { + fTree->Branch("bl_ts0", "std::vector", &_bl_ts0); + fTree->Branch("bl_ets0", "std::vector", &_bl_ets0); + fTree->Branch("bl_ts1", "std::vector", &_bl_ts1); + fTree->Branch("bl_ets1", "std::vector", &_bl_ets1); + fTree->Branch("bl_pe", "std::vector", &_bl_pe); + fTree->Branch("bl_nsps", "std::vector", &_bl_nsps); + fTree->Branch("bl_nsps_per_tagger", "std::vector>", &_bl_nsps_per_tagger); + } + if(!fNoTPC) { fTree->Branch("tpc_start_x", "std::vector", &_tpc_start_x); @@ -835,6 +862,23 @@ void sbnd::crt::CRTAnalysis::analyze(art::Event const& e) // Fill CRTTrack variables AnalyseCRTTracks(e, CRTTrackVec, tracksToSpacePoints, spacepointsToClusters, clustersToStripHits); + if(fHasBlobs) + { + // Get CRTBlobs + art::Handle> CRTBlobHandle; + e.getByLabel(fCRTBlobModuleLabel, CRTBlobHandle); + if(!CRTBlobHandle.isValid()){ + std::cout << "CRTBlob product " << fCRTBlobModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + std::vector> CRTBlobVec; + art::fill_ptr_vector(CRTBlobVec, CRTBlobHandle); + + // Fill CRTBlob variables + AnalyseCRTBlobs(CRTBlobVec); + } + if(fNoTPC) { // Fill the Tree @@ -1585,6 +1629,34 @@ void sbnd::crt::CRTAnalysis::AnalyseCRTTracks(const art::Event &e, const std::ve } } +void sbnd::crt::CRTAnalysis::AnalyseCRTBlobs(std::vector> &CRTBlobVec) +{ + const unsigned nBlobs = CRTBlobVec.size(); + + _bl_ts0.resize(nBlobs); + _bl_ets0.resize(nBlobs); + _bl_ts1.resize(nBlobs); + _bl_ets1.resize(nBlobs); + _bl_pe.resize(nBlobs); + _bl_nsps.resize(nBlobs); + _bl_nsps_per_tagger.resize(nBlobs, std::vector(7)); + + for(unsigned i = 0; i < nBlobs; ++i) + { + const auto blob = CRTBlobVec[i]; + + _bl_ts0[i] = blob->Ts0(); + _bl_ets0[i] = blob->Ts0Err(); + _bl_ts1[i] = blob->Ts1(); + _bl_ets1[i] = blob->Ts1Err(); + _bl_pe[i] = blob->PE(); + _bl_nsps[i] = blob->TotalSpacePoints(); + + for(unsigned j = 0; j < 7; ++j) + _bl_nsps_per_tagger[i][j] = blob->SpacePointsInTagger((CRTTagger)j); + } +} + void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art::Handle> &TPCTrackHandle, const art::Handle> &CRTSpacePointHandle, const art::Handle> &CRTClusterHandle, const art::Handle> &PFPHandle, From 8e22b42767fbac8142564403f919d28c5053cbbd Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 17 Feb 2026 11:01:51 -0600 Subject: [PATCH 26/75] Clean up fcls --- sbndcode/CRT/CRTReco/run_crtrecoana.fcl | 3 +++ sbndcode/CRT/CRTReco/run_crtrecoana_data.fcl | 3 +++ sbndcode/CRT/CRTReco/run_crtrecoana_notpc.fcl | 3 --- sbndcode/CRT/CRTReco/run_crtrecoana_notpc_no_flat_tracks.fcl | 3 --- 4 files changed, 6 insertions(+), 6 deletions(-) delete mode 100644 sbndcode/CRT/CRTReco/run_crtrecoana_notpc.fcl delete mode 100644 sbndcode/CRT/CRTReco/run_crtrecoana_notpc_no_flat_tracks.fcl diff --git a/sbndcode/CRT/CRTReco/run_crtrecoana.fcl b/sbndcode/CRT/CRTReco/run_crtrecoana.fcl index 6e9f6d8c8..15a37b22d 100644 --- a/sbndcode/CRT/CRTReco/run_crtrecoana.fcl +++ b/sbndcode/CRT/CRTReco/run_crtrecoana.fcl @@ -52,3 +52,6 @@ physics: trigger_paths: [ reco ] end_paths: [ ana, stream1 ] } + +physics.analyzers.crtana.HasBlobs: true +physics.analyzers.crtana.NoTPC: true diff --git a/sbndcode/CRT/CRTReco/run_crtrecoana_data.fcl b/sbndcode/CRT/CRTReco/run_crtrecoana_data.fcl index 11bbc53cf..c249a7d99 100644 --- a/sbndcode/CRT/CRTReco/run_crtrecoana_data.fcl +++ b/sbndcode/CRT/CRTReco/run_crtrecoana_data.fcl @@ -10,5 +10,8 @@ physics.producers.crtstrips: @local::crtstriphitproducer_data_sbnd physics.producers.crtclustering: @local::crtclusterproducer_data_sbnd physics.producers.crtspacepoints: @local::crtspacepointproducer_data_sbnd physics.producers.crttracks: @local::crttrackproducer_data_sbnd +physics.producers.crtblobs: @local::crtblobproducer_data_sbnd physics.analyzers.crtana: @local::crtana_data_sbnd +physics.analyzers.crtana.HasBlobs: true +physics.analyzers.crtana.NoTPC: true diff --git a/sbndcode/CRT/CRTReco/run_crtrecoana_notpc.fcl b/sbndcode/CRT/CRTReco/run_crtrecoana_notpc.fcl deleted file mode 100644 index 621b8d45a..000000000 --- a/sbndcode/CRT/CRTReco/run_crtrecoana_notpc.fcl +++ /dev/null @@ -1,3 +0,0 @@ -#include "run_crtrecoana.fcl" - -physics.analyzers.crtana.NoTPC: true diff --git a/sbndcode/CRT/CRTReco/run_crtrecoana_notpc_no_flat_tracks.fcl b/sbndcode/CRT/CRTReco/run_crtrecoana_notpc_no_flat_tracks.fcl deleted file mode 100644 index 74a8504d7..000000000 --- a/sbndcode/CRT/CRTReco/run_crtrecoana_notpc_no_flat_tracks.fcl +++ /dev/null @@ -1,3 +0,0 @@ -#include "run_crtrecoana_notpc.fcl" - -physics.producers.crttracks.MaskedTaggers: [ 0 ] From 2215cc314f4306603724241360c5a5eaebe025e1 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Wed, 18 Feb 2026 08:03:03 -0600 Subject: [PATCH 27/75] Manually check saturation --- sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc b/sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc index fe536a734..93eb61bfa 100644 --- a/sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc +++ b/sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc @@ -275,6 +275,10 @@ std::vector sbnd::crt::CRTStripHitProducer::CreateStripH const uint16_t adc1 = sipm1.pedestal < sipm_adcs[adc_i] ? sipm_adcs[adc_i] - sipm1.pedestal : 0; const uint16_t adc2 = sipm2.pedestal < sipm_adcs[adc_i+1] ? sipm_adcs[adc_i+1] - sipm2.pedestal : 0; + // Saturated? + const bool sat1 = sipm_adcs[adc_i] == fADCSaturation; + const bool sat2 = sipm_adcs[adc_i+1] == fADCSaturation; + // Keep hit if both SiPMs above threshold if(adc1 > fADCThreshold && adc2 > fADCThreshold) { @@ -292,7 +296,7 @@ std::vector sbnd::crt::CRTStripHitProducer::CreateStripH if(pos - err < 0) err = pos; - stripHits.emplace_back(offline_channel_id, t0, t1, ref_time_s, pos, err, adc1, adc2, fADCSaturation); + stripHits.emplace_back(offline_channel_id, t0, t1, ref_time_s, pos, err, adc1, adc2, sat1, sat2); } } From 6419fbf46a77d4a1e735336b2f0912cb2e86a8ae Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 6 Feb 2024 08:42:41 -0600 Subject: [PATCH 28/75] Add channel mapping version of module and relevant config --- sbndcode/CRT/CRTEventDisplay/CMakeLists.txt | 5 ++ .../CRTChannelMappingEventDisplay_module.cc | 90 +++++++++++++++++++ .../CRTEventDisplay/crteventdisplay_sbnd.fcl | 14 ++- .../crteventdisplayalg_sbnd.fcl | 24 +++++ .../run_crteventdisplay_channel_mapping.fcl | 29 ++++++ 5 files changed, 158 insertions(+), 4 deletions(-) create mode 100644 sbndcode/CRT/CRTEventDisplay/CRTChannelMappingEventDisplay_module.cc create mode 100644 sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping.fcl diff --git a/sbndcode/CRT/CRTEventDisplay/CMakeLists.txt b/sbndcode/CRT/CRTEventDisplay/CMakeLists.txt index 0a8aa82af..c245b2729 100644 --- a/sbndcode/CRT/CRTEventDisplay/CMakeLists.txt +++ b/sbndcode/CRT/CRTEventDisplay/CMakeLists.txt @@ -13,4 +13,9 @@ simple_plugin( sbndcode_CRT_CRTEventDisplay ) +simple_plugin( + CRTChannelMappingEventDisplay module + sbndcode_CRT_CRTEventDisplay +) + install_fhicl() diff --git a/sbndcode/CRT/CRTEventDisplay/CRTChannelMappingEventDisplay_module.cc b/sbndcode/CRT/CRTEventDisplay/CRTChannelMappingEventDisplay_module.cc new file mode 100644 index 000000000..99c4c1f6d --- /dev/null +++ b/sbndcode/CRT/CRTEventDisplay/CRTChannelMappingEventDisplay_module.cc @@ -0,0 +1,90 @@ +//////////////////////////////////////////////////////////////////////// +// Class: CRTChannelMappingEventDisplay +// Plugin Type: analyzer (Unknown Unknown) +// File: CRTChannelMappingEventDisplay_module.cc +// +// Generated at Thu Oct 6 09:32:09 2022 by Henry Lay using cetskelgen +// from version . +//////////////////////////////////////////////////////////////////////// + +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" +#include "art/Framework/Principal/SubRun.h" +#include "canvas/Utilities/InputTag.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" + +#include "lardata/DetectorInfoServices/DetectorClocksService.h" +#include "sbndcode/CRT/CRTEventDisplay/CRTEventDisplayAlg.h" + +#include "TSystem.h" + +namespace sbnd::crt { + class CRTChannelMappingEventDisplay; +} + +class sbnd::crt::CRTChannelMappingEventDisplay : public art::EDAnalyzer { +public: + + struct Config { + using Name = fhicl::Name; + using Comment = fhicl::Comment; + + fhicl::Table EventDisplayConfig { + Name("EventDisplayConfig"), + }; + + fhicl::Atom SaveDir { + Name("SaveDir"), + }; + }; + + using Parameters = art::EDAnalyzer::Table; + + explicit CRTChannelMappingEventDisplay(Parameters const &config); + + CRTChannelMappingEventDisplay(CRTChannelMappingEventDisplay const&) = delete; + CRTChannelMappingEventDisplay(CRTChannelMappingEventDisplay&&) = delete; + CRTChannelMappingEventDisplay& operator=(CRTChannelMappingEventDisplay const&) = delete; + CRTChannelMappingEventDisplay& operator=(CRTChannelMappingEventDisplay&&) = delete; + + void analyze(art::Event const& e) override; + +private: + + CRTEventDisplayAlg fCRTEventDisplayAlg; + CRTGeoAlg fCRTGeoAlg; + std::string fSaveDir; + std::vector fChosenTaggers; +}; + + +sbnd::crt::CRTChannelMappingEventDisplay::CRTChannelMappingEventDisplay(Parameters const& config) + : EDAnalyzer{config} + , fCRTEventDisplayAlg(config().EventDisplayConfig()) + , fCRTGeoAlg(config().EventDisplayConfig().GeoAlgConfig()) + , fSaveDir(config().SaveDir()) + , fChosenTaggers(config().EventDisplayConfig().ChosenTaggers()) + { + gSystem->Exec(Form("mkdir -p %s", fSaveDir.c_str())); + } + +void sbnd::crt::CRTChannelMappingEventDisplay::analyze(art::Event const& e) +{ + auto const clockData = art::ServiceHandle()->DataFor(e); + + for(auto const& [ name, module ] : fCRTGeoAlg.GetModules()) + { + if(std::find(fChosenTaggers.begin(), fChosenTaggers.end(), CRTCommonUtils::GetTaggerEnum(module.taggerName)) == fChosenTaggers.end()) + continue; + + fCRTEventDisplayAlg.SetHighlightedModules({module.adID}); + + fCRTEventDisplayAlg.Draw(clockData, e, Form("%s/%s", fSaveDir.c_str(), name.c_str())); + } +} + +DEFINE_ART_MODULE(sbnd::crt::CRTChannelMappingEventDisplay) diff --git a/sbndcode/CRT/CRTEventDisplay/crteventdisplay_sbnd.fcl b/sbndcode/CRT/CRTEventDisplay/crteventdisplay_sbnd.fcl index 03f656d3b..a64ede384 100644 --- a/sbndcode/CRT/CRTEventDisplay/crteventdisplay_sbnd.fcl +++ b/sbndcode/CRT/CRTEventDisplay/crteventdisplay_sbnd.fcl @@ -4,14 +4,20 @@ BEGIN_PROLOG crteventdisplay_sbnd: { - EventDisplayConfig: @local::crteventdisplayalg_sbnd - module_type: "CRTEventDisplay" + EventDisplayConfig: @local::crteventdisplayalg_sbnd + module_type: "CRTEventDisplay" } crteventdisplay_sbnd_data: { - EventDisplayConfig: @local::crteventdisplayalg_sbnd_data - module_type: "CRTEventDisplay" + EventDisplayConfig: @local::crteventdisplayalg_sbnd_data + module_type: "CRTEventDisplay" +} + +crteventdisplay_sbnd_channel_mapping: +{ + EventDisplayConfig: @local::crteventdisplayalg_sbnd_channel_mapping + module_type: "CRTChannelMappingEventDisplay" } END_PROLOG diff --git a/sbndcode/CRT/CRTEventDisplay/crteventdisplayalg_sbnd.fcl b/sbndcode/CRT/CRTEventDisplay/crteventdisplayalg_sbnd.fcl index a2bc90e24..1a5f77633 100644 --- a/sbndcode/CRT/CRTEventDisplay/crteventdisplayalg_sbnd.fcl +++ b/sbndcode/CRT/CRTEventDisplay/crteventdisplayalg_sbnd.fcl @@ -97,4 +97,28 @@ crteventdisplayalg_sbnd_data.UseTs0: true crteventdisplayalg_sbnd_data.MinTime: -1.5e6 crteventdisplayalg_sbnd_data.MaxTime: 1.5e6 +crteventdisplayalg_sbnd_channel_mapping: @local::crteventdisplayalg_sbnd + +crteventdisplayalg_sbnd_channel_mapping.DataMode: true +crteventdisplayalg_sbnd_channel_mapping.SaveRoot: false +crteventdisplayalg_sbnd_channel_mapping.SaveViews: true + +crteventdisplayalg_sbnd_channel_mapping.ChoseTaggers: true +crteventdisplayalg_sbnd_channel_mapping.HighlightModules: true + +crteventdisplayalg_sbnd_channel_mapping.DrawTaggers: true +crteventdisplayalg_sbnd_channel_mapping.DrawModules: true +crteventdisplayalg_sbnd_channel_mapping.DrawFEBs: true +crteventdisplayalg_sbnd_channel_mapping.DrawFEBEnds: true +crteventdisplayalg_sbnd_channel_mapping.DrawStrips: false +crteventdisplayalg_sbnd_channel_mapping.DrawTPC: true +crteventdisplayalg_sbnd_channel_mapping.DrawTrueTracks: false +crteventdisplayalg_sbnd_channel_mapping.DrawSimDeposits: false +crteventdisplayalg_sbnd_channel_mapping.DrawStripHits: false +crteventdisplayalg_sbnd_channel_mapping.DrawClusters: false +crteventdisplayalg_sbnd_channel_mapping.DrawSpacePoints: false +crteventdisplayalg_sbnd_channel_mapping.DrawTracks: false + +crteventdisplayalg_sbnd_channel_mapping.Print: false + END_PROLOG diff --git a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping.fcl b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping.fcl new file mode 100644 index 000000000..03ab48cad --- /dev/null +++ b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping.fcl @@ -0,0 +1,29 @@ +#include "services_sbnd.fcl" +#include "crt_services_sbnd.fcl" +#include "crteventdisplay_sbnd.fcl" + +process_name: CRTEventDisplay + +services: +{ + @table::sbnd_services + @table::crt_services_data_sbnd +} + +source: +{ + module_type: RootInput + maxEvents: -1 +} + +physics: +{ + analyzers: + { + crtevd: @local::crteventdisplay_sbnd_channel_mapping + } + + ana: [ crtevd ] + + end_paths: [ ana ] +} From bb8dc73da55bcc57d140f208fa4a3d7eb906fd31 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 6 Feb 2024 08:45:26 -0600 Subject: [PATCH 29/75] Add bash script for making pdf --- sbndcode/CRT/CRTEventDisplay/build_tex.sh | 70 +++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 sbndcode/CRT/CRTEventDisplay/build_tex.sh diff --git a/sbndcode/CRT/CRTEventDisplay/build_tex.sh b/sbndcode/CRT/CRTEventDisplay/build_tex.sh new file mode 100644 index 000000000..77ff9a4e9 --- /dev/null +++ b/sbndcode/CRT/CRTEventDisplay/build_tex.sh @@ -0,0 +1,70 @@ +echo "\documentclass{article} +\usepackage[a4paper, margin=3cm]{geometry} +\usepackage{graphicx} +\usepackage{pgffor} +\usepackage[hidelinks]{hyperref} + +\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode v09\_82\_02\_01} \textit{\&} \texttt{sbnd\_v02\_00.gdml}} +\author{Henry Lay \\\\ \small h.lay@lancaster.ac.uk}" > crt_channel_mapping_evds.tex + +walls=(bottom south north west east toplow tophigh) +wallnames=(Bottom South North West East "Top Low" "Top High") + +for wall in "${walls[@]}" +do + list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/${wall}_wall/*_front.pdf) + echo -n "\newcommand*{\\"$wall"ids}{" >> crt_channel_mapping_evds.tex + + for item in ${list} + do + name=$(echo $item | cut -d '/' -f 9) + number=$(echo $name | cut -d '_' -f 2) + echo -n $number, >> crt_channel_mapping_evds.tex + done + + sed -i '$ s/.$//' crt_channel_mapping_evds.tex + echo "}" >> crt_channel_mapping_evds.tex +done + +echo "\begin{document} + +\maketitle + +\centering +\vspace{2em} + +\includegraphics[width=.6\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/luphysics_logo.png} + +\vspace{2em} + +\includegraphics[width=.5\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/sbnd_pride_transparent.png} +\flushleft +\newpage +\tableofcontents +\newpage +\section{Explanation} +This document contains a series of illustrations created using the \texttt{CRTEventDisplay} tool originally written by Tom Brooks \& heavily developed by myself. It shows the position of the various CRT modules according to the gdml file used in SBND simulation and reconstruction. The document is split into sections for the different tagger walls. For each module three illustrations are provided: front, top and side views. The axes show detector coordinates (X, Y and Z) and \`\`building coordinates\" (South, West and Up). The relevant module is shown in green. The TPCs are shown in grey in the centre for reference. The black outer is the full tagger wall. The thin grey are other modules in the wall. The red is the FEB position and the blue corresponds to the end of the FEB with channel 0 (the ethernet ports). +" >> crt_channel_mapping_evds.tex + +for i in "${!walls[@]}" +do + echo "\newpage +\section{${wallnames[i]} Wall} +\begingroup +\foreach \x in \\${walls[i]}ids +{ + \newpage + \subsection{volCRTModule\x\_\x} + \begin{center} + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} + \end{center} +} +\endgroup" >> crt_channel_mapping_evds.tex +done + +echo "\end{document}" >> crt_channel_mapping_evds.tex + +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/tex_work crt_channel_mapping_evds.tex From 50586c9641a0faface2968055adfca6bc4485702 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 6 Feb 2024 08:53:12 -0600 Subject: [PATCH 30/75] Z points North not South, duh --- sbndcode/CRT/CRTEventDisplay/build_tex.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbndcode/CRT/CRTEventDisplay/build_tex.sh b/sbndcode/CRT/CRTEventDisplay/build_tex.sh index 77ff9a4e9..a82faa13f 100644 --- a/sbndcode/CRT/CRTEventDisplay/build_tex.sh +++ b/sbndcode/CRT/CRTEventDisplay/build_tex.sh @@ -43,7 +43,7 @@ echo "\begin{document} \tableofcontents \newpage \section{Explanation} -This document contains a series of illustrations created using the \texttt{CRTEventDisplay} tool originally written by Tom Brooks \& heavily developed by myself. It shows the position of the various CRT modules according to the gdml file used in SBND simulation and reconstruction. The document is split into sections for the different tagger walls. For each module three illustrations are provided: front, top and side views. The axes show detector coordinates (X, Y and Z) and \`\`building coordinates\" (South, West and Up). The relevant module is shown in green. The TPCs are shown in grey in the centre for reference. The black outer is the full tagger wall. The thin grey are other modules in the wall. The red is the FEB position and the blue corresponds to the end of the FEB with channel 0 (the ethernet ports). +This document contains a series of illustrations created using the \texttt{CRTEventDisplay} tool originally written by Tom Brooks \& heavily developed by myself. It shows the position of the various CRT modules according to the gdml file used in SBND simulation and reconstruction. The document is split into sections for the different tagger walls. For each module three illustrations are provided: front, top and side views. The axes show detector coordinates (X, Y and Z) and \`\`building coordinates\" (North, West and Up). The relevant module is shown in green. The TPCs are shown in grey in the centre for reference. The black outer is the full tagger wall. The thin grey are other modules in the wall. The red is the FEB position and the blue corresponds to the end of the FEB with channel 0 (the ethernet ports). " >> crt_channel_mapping_evds.tex for i in "${!walls[@]}" From 184da01079e3bc8542a4a029f8654667d740e5a4 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 24 Jun 2024 11:09:03 -0500 Subject: [PATCH 31/75] Update channel map evds to test David's updates --- sbndcode/CRT/CRTEventDisplay/build_tex.sh | 24 ++++----- ...un_crteventdisplay_channel_mapping_all.fcl | 53 +++++++++++++++++++ 2 files changed, 65 insertions(+), 12 deletions(-) create mode 100644 sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl diff --git a/sbndcode/CRT/CRTEventDisplay/build_tex.sh b/sbndcode/CRT/CRTEventDisplay/build_tex.sh index a82faa13f..1c3f2db41 100644 --- a/sbndcode/CRT/CRTEventDisplay/build_tex.sh +++ b/sbndcode/CRT/CRTEventDisplay/build_tex.sh @@ -4,7 +4,7 @@ echo "\documentclass{article} \usepackage{pgffor} \usepackage[hidelinks]{hyperref} -\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode v09\_82\_02\_01} \textit{\&} \texttt{sbnd\_v02\_00.gdml}} +\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode v09\_90\_00} \textit{\&} \texttt{sbnd\_v02\_01.gdml}} \author{Henry Lay \\\\ \small h.lay@lancaster.ac.uk}" > crt_channel_mapping_evds.tex walls=(bottom south north west east toplow tophigh) @@ -12,14 +12,14 @@ wallnames=(Bottom South North West East "Top Low" "Top High") for wall in "${walls[@]}" do - list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/${wall}_wall/*_front.pdf) + list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/${wall}_wall/*_front.pdf) echo -n "\newcommand*{\\"$wall"ids}{" >> crt_channel_mapping_evds.tex for item in ${list} do - name=$(echo $item | cut -d '/' -f 9) - number=$(echo $name | cut -d '_' -f 2) - echo -n $number, >> crt_channel_mapping_evds.tex + name=$(echo $item | cut -d '/' -f 10) + number=$(echo $name | cut -d '_' -f 2) + echo -n $number, >> crt_channel_mapping_evds.tex done sed -i '$ s/.$//' crt_channel_mapping_evds.tex @@ -33,11 +33,11 @@ echo "\begin{document} \centering \vspace{2em} -\includegraphics[width=.6\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/luphysics_logo.png} +\includegraphics[width=.6\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/luphysics_logo.png} \vspace{2em} -\includegraphics[width=.5\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/sbnd_pride_transparent.png} +\includegraphics[width=.5\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/sbnd_pride_transparent.png} \flushleft \newpage \tableofcontents @@ -56,9 +56,9 @@ do \newpage \subsection{volCRTModule\x\_\x} \begin{center} - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} \end{center} } \endgroup" >> crt_channel_mapping_evds.tex @@ -66,5 +66,5 @@ done echo "\end{document}" >> crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/tex_work crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/tex_work crt_channel_mapping_evds.tex diff --git a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl new file mode 100644 index 000000000..ec5d3b264 --- /dev/null +++ b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl @@ -0,0 +1,53 @@ +#include "crt_channel_map_service.fcl" +#include "crt_calib_service.fcl" +#include "run_crteventdisplay_channel_mapping.fcl" + +process_name: CRTEventDisplay + +services: +{ + @table::sbnd_services + ParticleInventoryService: @local::standard_particleinventoryservice + CRTChannelMapService: @local::crt_channel_map_standard + CRTCalibService: @local::crt_calib_service +} + +source: +{ + module_type: RootInput + maxEvents: -1 + +} + +physics: +{ + analyzers: + { + crtevdbot: @local::crteventdisplay_sbnd_channel_mapping + crtevdsou: @local::crteventdisplay_sbnd_channel_mapping + crtevdnor: @local::crteventdisplay_sbnd_channel_mapping + crtevdwes: @local::crteventdisplay_sbnd_channel_mapping + crtevdeas: @local::crteventdisplay_sbnd_channel_mapping + crtevdtpl: @local::crteventdisplay_sbnd_channel_mapping + crtevdtph: @local::crteventdisplay_sbnd_channel_mapping + } + + ana: [ crtevdbot, crtevdsou, crtevdnor, crtevdwes, crtevdeas, crtevdtpl, crtevdtph ] + + end_paths: [ ana ] +} + +physics.analyzers.crtevdbot.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/bottom_wall" +physics.analyzers.crtevdbot.EventDisplayConfig.ChosenTaggers: [ 0 ] +physics.analyzers.crtevdsou.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/south_wall" +physics.analyzers.crtevdsou.EventDisplayConfig.ChosenTaggers: [ 1 ] +physics.analyzers.crtevdnor.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/north_wall" +physics.analyzers.crtevdnor.EventDisplayConfig.ChosenTaggers: [ 2 ] +physics.analyzers.crtevdwes.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/west_wall" +physics.analyzers.crtevdwes.EventDisplayConfig.ChosenTaggers: [ 3 ] +physics.analyzers.crtevdeas.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/east_wall" +physics.analyzers.crtevdeas.EventDisplayConfig.ChosenTaggers: [ 4 ] +physics.analyzers.crtevdtpl.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/toplow_wall" +physics.analyzers.crtevdtpl.EventDisplayConfig.ChosenTaggers: [ 5 ] +physics.analyzers.crtevdtph.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/tophigh_wall" +physics.analyzers.crtevdtph.EventDisplayConfig.ChosenTaggers: [ 6 ] From f97696f3f24dfcdf50c2598aee82d0daf330f46e Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Sun, 25 Aug 2024 18:03:40 -0500 Subject: [PATCH 32/75] New CRT gdml channel mapping evds --- sbndcode/CRT/CRTEventDisplay/build_tex.sh | 18 +++++++++--------- ...run_crteventdisplay_channel_mapping_all.fcl | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sbndcode/CRT/CRTEventDisplay/build_tex.sh b/sbndcode/CRT/CRTEventDisplay/build_tex.sh index 1c3f2db41..fdaef5ded 100644 --- a/sbndcode/CRT/CRTEventDisplay/build_tex.sh +++ b/sbndcode/CRT/CRTEventDisplay/build_tex.sh @@ -4,7 +4,7 @@ echo "\documentclass{article} \usepackage{pgffor} \usepackage[hidelinks]{hyperref} -\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode v09\_90\_00} \textit{\&} \texttt{sbnd\_v02\_01.gdml}} +\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode v09\_90\_00} \textit{\&} \texttt{sbnd\_v02\_02.gdml}} \author{Henry Lay \\\\ \small h.lay@lancaster.ac.uk}" > crt_channel_mapping_evds.tex walls=(bottom south north west east toplow tophigh) @@ -12,7 +12,7 @@ wallnames=(Bottom South North West East "Top Low" "Top High") for wall in "${walls[@]}" do - list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/${wall}_wall/*_front.pdf) + list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/${wall}_wall/*_front.pdf) echo -n "\newcommand*{\\"$wall"ids}{" >> crt_channel_mapping_evds.tex for item in ${list} @@ -33,11 +33,11 @@ echo "\begin{document} \centering \vspace{2em} -\includegraphics[width=.6\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/luphysics_logo.png} +\includegraphics[width=.6\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/luphysics_logo.png} \vspace{2em} -\includegraphics[width=.5\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/sbnd_pride_transparent.png} +\includegraphics[width=.5\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/sbnd_pride_transparent.png} \flushleft \newpage \tableofcontents @@ -56,9 +56,9 @@ do \newpage \subsection{volCRTModule\x\_\x} \begin{center} - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} \end{center} } \endgroup" >> crt_channel_mapping_evds.tex @@ -66,5 +66,5 @@ done echo "\end{document}" >> crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/tex_work crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/tex_work crt_channel_mapping_evds.tex diff --git a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl index ec5d3b264..719321a2b 100644 --- a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl +++ b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl @@ -37,17 +37,17 @@ physics: end_paths: [ ana ] } -physics.analyzers.crtevdbot.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/bottom_wall" +physics.analyzers.crtevdbot.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/bottom_wall" physics.analyzers.crtevdbot.EventDisplayConfig.ChosenTaggers: [ 0 ] -physics.analyzers.crtevdsou.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/south_wall" +physics.analyzers.crtevdsou.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/south_wall" physics.analyzers.crtevdsou.EventDisplayConfig.ChosenTaggers: [ 1 ] -physics.analyzers.crtevdnor.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/north_wall" +physics.analyzers.crtevdnor.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/north_wall" physics.analyzers.crtevdnor.EventDisplayConfig.ChosenTaggers: [ 2 ] -physics.analyzers.crtevdwes.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/west_wall" +physics.analyzers.crtevdwes.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/west_wall" physics.analyzers.crtevdwes.EventDisplayConfig.ChosenTaggers: [ 3 ] -physics.analyzers.crtevdeas.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/east_wall" +physics.analyzers.crtevdeas.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/east_wall" physics.analyzers.crtevdeas.EventDisplayConfig.ChosenTaggers: [ 4 ] -physics.analyzers.crtevdtpl.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/toplow_wall" +physics.analyzers.crtevdtpl.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/toplow_wall" physics.analyzers.crtevdtpl.EventDisplayConfig.ChosenTaggers: [ 5 ] -physics.analyzers.crtevdtph.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/june2024/tophigh_wall" +physics.analyzers.crtevdtph.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/tophigh_wall" physics.analyzers.crtevdtph.EventDisplayConfig.ChosenTaggers: [ 6 ] From 27d0e16b801331255df5cdb70543cdc7021897cd Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Sat, 28 Sep 2024 06:36:48 -0500 Subject: [PATCH 33/75] Changes to channel map evd producer --- sbndcode/CRT/CRTEventDisplay/build_tex.sh | 21 +++++++++---------- ...un_crteventdisplay_channel_mapping_all.fcl | 18 +++++++++------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/sbndcode/CRT/CRTEventDisplay/build_tex.sh b/sbndcode/CRT/CRTEventDisplay/build_tex.sh index fdaef5ded..ff75ab234 100644 --- a/sbndcode/CRT/CRTEventDisplay/build_tex.sh +++ b/sbndcode/CRT/CRTEventDisplay/build_tex.sh @@ -4,15 +4,15 @@ echo "\documentclass{article} \usepackage{pgffor} \usepackage[hidelinks]{hyperref} -\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode v09\_90\_00} \textit{\&} \texttt{sbnd\_v02\_02.gdml}} -\author{Henry Lay \\\\ \small h.lay@lancaster.ac.uk}" > crt_channel_mapping_evds.tex +\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode v09\_91\_02\_02} \textit{\&} \texttt{sbnd\_v02\_03.gdml}} +\author{Henry Lay \\\\ \small h.lay@sheffield.ac.uk}" > crt_channel_mapping_evds.tex walls=(bottom south north west east toplow tophigh) wallnames=(Bottom South North West East "Top Low" "Top High") for wall in "${walls[@]}" do - list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/${wall}_wall/*_front.pdf) + list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/${wall}_wall/*_front.pdf) echo -n "\newcommand*{\\"$wall"ids}{" >> crt_channel_mapping_evds.tex for item in ${list} @@ -33,11 +33,10 @@ echo "\begin{document} \centering \vspace{2em} -\includegraphics[width=.6\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/luphysics_logo.png} - +\includegraphics[width=.6\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/UOSLogo_Primary_Violet_RGB.png} \vspace{2em} -\includegraphics[width=.5\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/sbnd_pride_transparent.png} +\includegraphics[width=.5\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/sbnd_pride_transparent.png} \flushleft \newpage \tableofcontents @@ -56,9 +55,9 @@ do \newpage \subsection{volCRTModule\x\_\x} \begin{center} - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} \end{center} } \endgroup" >> crt_channel_mapping_evds.tex @@ -66,5 +65,5 @@ done echo "\end{document}" >> crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/tex_work crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/tex_work crt_channel_mapping_evds.tex diff --git a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl index 719321a2b..2e8f01d5e 100644 --- a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl +++ b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl @@ -1,6 +1,8 @@ +#include "services_sbnd.fcl" +#include "particleinventoryservice.fcl" +#include "crteventdisplay_sbnd.fcl" #include "crt_channel_map_service.fcl" #include "crt_calib_service.fcl" -#include "run_crteventdisplay_channel_mapping.fcl" process_name: CRTEventDisplay @@ -37,17 +39,17 @@ physics: end_paths: [ ana ] } -physics.analyzers.crtevdbot.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/bottom_wall" +physics.analyzers.crtevdbot.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/bottom_wall" physics.analyzers.crtevdbot.EventDisplayConfig.ChosenTaggers: [ 0 ] -physics.analyzers.crtevdsou.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/south_wall" +physics.analyzers.crtevdsou.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/south_wall" physics.analyzers.crtevdsou.EventDisplayConfig.ChosenTaggers: [ 1 ] -physics.analyzers.crtevdnor.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/north_wall" +physics.analyzers.crtevdnor.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/north_wall" physics.analyzers.crtevdnor.EventDisplayConfig.ChosenTaggers: [ 2 ] -physics.analyzers.crtevdwes.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/west_wall" +physics.analyzers.crtevdwes.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/west_wall" physics.analyzers.crtevdwes.EventDisplayConfig.ChosenTaggers: [ 3 ] -physics.analyzers.crtevdeas.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/east_wall" +physics.analyzers.crtevdeas.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/east_wall" physics.analyzers.crtevdeas.EventDisplayConfig.ChosenTaggers: [ 4 ] -physics.analyzers.crtevdtpl.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/toplow_wall" +physics.analyzers.crtevdtpl.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/toplow_wall" physics.analyzers.crtevdtpl.EventDisplayConfig.ChosenTaggers: [ 5 ] -physics.analyzers.crtevdtph.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/august2024/tophigh_wall" +physics.analyzers.crtevdtph.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/tophigh_wall" physics.analyzers.crtevdtph.EventDisplayConfig.ChosenTaggers: [ 6 ] From 25bc90306d11828419ae82d37c90a654e2bda540 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 27 Jan 2025 05:46:58 -0600 Subject: [PATCH 34/75] New round of channel map evds --- sbndcode/CRT/CRTEventDisplay/build_tex.sh | 18 +++++++++--------- ...run_crteventdisplay_channel_mapping_all.fcl | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sbndcode/CRT/CRTEventDisplay/build_tex.sh b/sbndcode/CRT/CRTEventDisplay/build_tex.sh index ff75ab234..727298f54 100644 --- a/sbndcode/CRT/CRTEventDisplay/build_tex.sh +++ b/sbndcode/CRT/CRTEventDisplay/build_tex.sh @@ -4,7 +4,7 @@ echo "\documentclass{article} \usepackage{pgffor} \usepackage[hidelinks]{hyperref} -\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode v09\_91\_02\_02} \textit{\&} \texttt{sbnd\_v02\_03.gdml}} +\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode v09\_93\_01\_02} \textit{\&} \texttt{sbnd\_v02\_03.gdml}} \author{Henry Lay \\\\ \small h.lay@sheffield.ac.uk}" > crt_channel_mapping_evds.tex walls=(bottom south north west east toplow tophigh) @@ -12,7 +12,7 @@ wallnames=(Bottom South North West East "Top Low" "Top High") for wall in "${walls[@]}" do - list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/${wall}_wall/*_front.pdf) + list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/${wall}_wall/*_front.pdf) echo -n "\newcommand*{\\"$wall"ids}{" >> crt_channel_mapping_evds.tex for item in ${list} @@ -33,10 +33,10 @@ echo "\begin{document} \centering \vspace{2em} -\includegraphics[width=.6\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/UOSLogo_Primary_Violet_RGB.png} +\includegraphics[width=.6\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/UOSLogo_Primary_Violet_RGB.png} \vspace{2em} -\includegraphics[width=.5\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/sbnd_pride_transparent.png} +\includegraphics[width=.5\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/sbnd_pride_transparent.png} \flushleft \newpage \tableofcontents @@ -55,9 +55,9 @@ do \newpage \subsection{volCRTModule\x\_\x} \begin{center} - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} \end{center} } \endgroup" >> crt_channel_mapping_evds.tex @@ -65,5 +65,5 @@ done echo "\end{document}" >> crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/tex_work crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/tex_work crt_channel_mapping_evds.tex diff --git a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl index 2e8f01d5e..674c5ee6b 100644 --- a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl +++ b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl @@ -39,17 +39,17 @@ physics: end_paths: [ ana ] } -physics.analyzers.crtevdbot.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/bottom_wall" +physics.analyzers.crtevdbot.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/bottom_wall" physics.analyzers.crtevdbot.EventDisplayConfig.ChosenTaggers: [ 0 ] -physics.analyzers.crtevdsou.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/south_wall" +physics.analyzers.crtevdsou.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/south_wall" physics.analyzers.crtevdsou.EventDisplayConfig.ChosenTaggers: [ 1 ] -physics.analyzers.crtevdnor.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/north_wall" +physics.analyzers.crtevdnor.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/north_wall" physics.analyzers.crtevdnor.EventDisplayConfig.ChosenTaggers: [ 2 ] -physics.analyzers.crtevdwes.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/west_wall" +physics.analyzers.crtevdwes.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/west_wall" physics.analyzers.crtevdwes.EventDisplayConfig.ChosenTaggers: [ 3 ] -physics.analyzers.crtevdeas.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/east_wall" +physics.analyzers.crtevdeas.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/east_wall" physics.analyzers.crtevdeas.EventDisplayConfig.ChosenTaggers: [ 4 ] -physics.analyzers.crtevdtpl.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/toplow_wall" +physics.analyzers.crtevdtpl.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/toplow_wall" physics.analyzers.crtevdtpl.EventDisplayConfig.ChosenTaggers: [ 5 ] -physics.analyzers.crtevdtph.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/oct2024/tophigh_wall" +physics.analyzers.crtevdtph.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/tophigh_wall" physics.analyzers.crtevdtph.EventDisplayConfig.ChosenTaggers: [ 6 ] From a30a782c052e408da79119d4ff73133c9c1ffc02 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 15 May 2025 10:24:42 -0500 Subject: [PATCH 35/75] Updated CRT channel mapping display --- sbndcode/CRT/CRTEventDisplay/build_tex.sh | 18 +++++++++--------- ...run_crteventdisplay_channel_mapping_all.fcl | 14 +++++++------- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/sbndcode/CRT/CRTEventDisplay/build_tex.sh b/sbndcode/CRT/CRTEventDisplay/build_tex.sh index 727298f54..2f4053d7f 100644 --- a/sbndcode/CRT/CRTEventDisplay/build_tex.sh +++ b/sbndcode/CRT/CRTEventDisplay/build_tex.sh @@ -4,7 +4,7 @@ echo "\documentclass{article} \usepackage{pgffor} \usepackage[hidelinks]{hyperref} -\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode v09\_93\_01\_02} \textit{\&} \texttt{sbnd\_v02\_03.gdml}} +\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode v10\_04\_01} \textit{\&} \texttt{sbnd\_v02\_05.gdml}} \author{Henry Lay \\\\ \small h.lay@sheffield.ac.uk}" > crt_channel_mapping_evds.tex walls=(bottom south north west east toplow tophigh) @@ -12,7 +12,7 @@ wallnames=(Bottom South North West East "Top Low" "Top High") for wall in "${walls[@]}" do - list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/${wall}_wall/*_front.pdf) + list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/${wall}_wall/*_front.pdf) echo -n "\newcommand*{\\"$wall"ids}{" >> crt_channel_mapping_evds.tex for item in ${list} @@ -33,10 +33,10 @@ echo "\begin{document} \centering \vspace{2em} -\includegraphics[width=.6\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/UOSLogo_Primary_Violet_RGB.png} +\includegraphics[width=.6\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/UOSLogo_Primary_Violet_RGB.png} \vspace{2em} -\includegraphics[width=.5\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/sbnd_pride_transparent.png} +\includegraphics[width=.5\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/sbnd_pride_transparent.png} \flushleft \newpage \tableofcontents @@ -55,9 +55,9 @@ do \newpage \subsection{volCRTModule\x\_\x} \begin{center} - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} \end{center} } \endgroup" >> crt_channel_mapping_evds.tex @@ -65,5 +65,5 @@ done echo "\end{document}" >> crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/tex_work crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/tex_work crt_channel_mapping_evds.tex diff --git a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl index 674c5ee6b..9b8275177 100644 --- a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl +++ b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl @@ -39,17 +39,17 @@ physics: end_paths: [ ana ] } -physics.analyzers.crtevdbot.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/bottom_wall" +physics.analyzers.crtevdbot.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/bottom_wall" physics.analyzers.crtevdbot.EventDisplayConfig.ChosenTaggers: [ 0 ] -physics.analyzers.crtevdsou.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/south_wall" +physics.analyzers.crtevdsou.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/south_wall" physics.analyzers.crtevdsou.EventDisplayConfig.ChosenTaggers: [ 1 ] -physics.analyzers.crtevdnor.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/north_wall" +physics.analyzers.crtevdnor.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/north_wall" physics.analyzers.crtevdnor.EventDisplayConfig.ChosenTaggers: [ 2 ] -physics.analyzers.crtevdwes.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/west_wall" +physics.analyzers.crtevdwes.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/west_wall" physics.analyzers.crtevdwes.EventDisplayConfig.ChosenTaggers: [ 3 ] -physics.analyzers.crtevdeas.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/east_wall" +physics.analyzers.crtevdeas.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/east_wall" physics.analyzers.crtevdeas.EventDisplayConfig.ChosenTaggers: [ 4 ] -physics.analyzers.crtevdtpl.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/toplow_wall" +physics.analyzers.crtevdtpl.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/toplow_wall" physics.analyzers.crtevdtpl.EventDisplayConfig.ChosenTaggers: [ 5 ] -physics.analyzers.crtevdtph.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/jan2025/tophigh_wall" +physics.analyzers.crtevdtph.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/tophigh_wall" physics.analyzers.crtevdtph.EventDisplayConfig.ChosenTaggers: [ 6 ] From 380b27fcfb124f16d2d01df7dec8bb1c7fdf0778 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Fri, 20 Feb 2026 10:41:52 -0600 Subject: [PATCH 36/75] Make tex script more configurable --- sbndcode/CRT/CRTEventDisplay/build_tex.sh | 28 +++++++++++++++-------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/sbndcode/CRT/CRTEventDisplay/build_tex.sh b/sbndcode/CRT/CRTEventDisplay/build_tex.sh index 2f4053d7f..decfbc43e 100644 --- a/sbndcode/CRT/CRTEventDisplay/build_tex.sh +++ b/sbndcode/CRT/CRTEventDisplay/build_tex.sh @@ -1,18 +1,26 @@ +version=$1 +gdml=$2 +author=$3 +email=$4 +edition=$5 + +mkdir /exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/tex_work + echo "\documentclass{article} \usepackage[a4paper, margin=3cm]{geometry} \usepackage{graphicx} \usepackage{pgffor} \usepackage[hidelinks]{hyperref} -\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode v10\_04\_01} \textit{\&} \texttt{sbnd\_v02\_05.gdml}} -\author{Henry Lay \\\\ \small h.lay@sheffield.ac.uk}" > crt_channel_mapping_evds.tex +\title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode ${version}} \textit{\&} \texttt{${gdml}}} +\author{${author} \\\\ \small ${email}}" > crt_channel_mapping_evds.tex walls=(bottom south north west east toplow tophigh) wallnames=(Bottom South North West East "Top Low" "Top High") for wall in "${walls[@]}" do - list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/${wall}_wall/*_front.pdf) + list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/${wall}_wall/*_front.pdf) echo -n "\newcommand*{\\"$wall"ids}{" >> crt_channel_mapping_evds.tex for item in ${list} @@ -33,10 +41,10 @@ echo "\begin{document} \centering \vspace{2em} -\includegraphics[width=.6\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/UOSLogo_Primary_Violet_RGB.png} +\includegraphics[width=.6\textwidth]{/nashome/h/hlay/UOSLogo_Primary_Violet_RGB.png} \vspace{2em} -\includegraphics[width=.5\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/sbnd_pride_transparent.png} +\includegraphics[width=.5\textwidth]{/nashome/h/hlay/sbnd_pride_transparent.png} \flushleft \newpage \tableofcontents @@ -55,9 +63,9 @@ do \newpage \subsection{volCRTModule\x\_\x} \begin{center} - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ + \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} \end{center} } \endgroup" >> crt_channel_mapping_evds.tex @@ -65,5 +73,5 @@ done echo "\end{document}" >> crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/tex_work crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/tex_work crt_channel_mapping_evds.tex From 9a5c2ed58b9b87dcbd9b9e42baa20afcee0de149 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Fri, 20 Feb 2026 10:47:13 -0600 Subject: [PATCH 37/75] Make compatible with current develop --- .../CRTChannelMappingEventDisplay_module.cc | 11 +++++------ .../run_crteventdisplay_channel_mapping_all.fcl | 7 +++---- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/sbndcode/CRT/CRTEventDisplay/CRTChannelMappingEventDisplay_module.cc b/sbndcode/CRT/CRTEventDisplay/CRTChannelMappingEventDisplay_module.cc index 99c4c1f6d..cfa00cd45 100644 --- a/sbndcode/CRT/CRTEventDisplay/CRTChannelMappingEventDisplay_module.cc +++ b/sbndcode/CRT/CRTEventDisplay/CRTChannelMappingEventDisplay_module.cc @@ -55,17 +55,16 @@ class sbnd::crt::CRTChannelMappingEventDisplay : public art::EDAnalyzer { private: - CRTEventDisplayAlg fCRTEventDisplayAlg; - CRTGeoAlg fCRTGeoAlg; - std::string fSaveDir; - std::vector fChosenTaggers; + CRTEventDisplayAlg fCRTEventDisplayAlg; + art::ServiceHandle fCRTGeoService; + std::string fSaveDir; + std::vector fChosenTaggers; }; sbnd::crt::CRTChannelMappingEventDisplay::CRTChannelMappingEventDisplay(Parameters const& config) : EDAnalyzer{config} , fCRTEventDisplayAlg(config().EventDisplayConfig()) - , fCRTGeoAlg(config().EventDisplayConfig().GeoAlgConfig()) , fSaveDir(config().SaveDir()) , fChosenTaggers(config().EventDisplayConfig().ChosenTaggers()) { @@ -76,7 +75,7 @@ void sbnd::crt::CRTChannelMappingEventDisplay::analyze(art::Event const& e) { auto const clockData = art::ServiceHandle()->DataFor(e); - for(auto const& [ name, module ] : fCRTGeoAlg.GetModules()) + for(auto const& [ name, module ] : fCRTGeoService->GetModules()) { if(std::find(fChosenTaggers.begin(), fChosenTaggers.end(), CRTCommonUtils::GetTaggerEnum(module.taggerName)) == fChosenTaggers.end()) continue; diff --git a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl index 9b8275177..435e34615 100644 --- a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl +++ b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl @@ -1,17 +1,16 @@ #include "services_sbnd.fcl" #include "particleinventoryservice.fcl" #include "crteventdisplay_sbnd.fcl" -#include "crt_channel_map_service.fcl" -#include "crt_calib_service.fcl" +#include "crt_services_sbnd.fcl" process_name: CRTEventDisplay services: { @table::sbnd_services + @table::crt_services_sbnd ParticleInventoryService: @local::standard_particleinventoryservice - CRTChannelMapService: @local::crt_channel_map_standard - CRTCalibService: @local::crt_calib_service + CRTChannelMapService: @local::crt_channel_map_no_inversion } source: From a196d7cb330d8b767e5ba68d32bf1ddfe4e1e5b1 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Fri, 20 Feb 2026 11:23:09 -0600 Subject: [PATCH 38/75] Remove unnecessary fcl --- .../run_crteventdisplay_channel_mapping.fcl | 29 ------------------- 1 file changed, 29 deletions(-) delete mode 100644 sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping.fcl diff --git a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping.fcl b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping.fcl deleted file mode 100644 index 03ab48cad..000000000 --- a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping.fcl +++ /dev/null @@ -1,29 +0,0 @@ -#include "services_sbnd.fcl" -#include "crt_services_sbnd.fcl" -#include "crteventdisplay_sbnd.fcl" - -process_name: CRTEventDisplay - -services: -{ - @table::sbnd_services - @table::crt_services_data_sbnd -} - -source: -{ - module_type: RootInput - maxEvents: -1 -} - -physics: -{ - analyzers: - { - crtevd: @local::crteventdisplay_sbnd_channel_mapping - } - - ana: [ crtevd ] - - end_paths: [ ana ] -} From b36419cd57b17ef350b19cd16132d56f7d1afc70 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 9 Jul 2024 06:46:07 -0500 Subject: [PATCH 39/75] Add functionality for turning off inversion - useful for the channel mapping event displays --- .../CRT/SBNDCRTChannelMap_v5_no_inversion.txt | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 sbndcode/ChannelMaps/CRT/SBNDCRTChannelMap_v5_no_inversion.txt diff --git a/sbndcode/ChannelMaps/CRT/SBNDCRTChannelMap_v5_no_inversion.txt b/sbndcode/ChannelMaps/CRT/SBNDCRTChannelMap_v5_no_inversion.txt new file mode 100644 index 000000000..7e0478c14 --- /dev/null +++ b/sbndcode/ChannelMaps/CRT/SBNDCRTChannelMap_v5_no_inversion.txt @@ -0,0 +1,87 @@ +40 173 0 +41 172 0 +42 168 0 +43 170 0 +44 176 0 +45 59 0 +46 171 0 +47 61 0 +48 166 0 +49 169 0 +50 56 0 +51 60 0 +52 34 0 +53 33 0 +54 57 0 +55 24 0 +56 159 0 +57 153 0 +58 156 0 +59 152 0 +60 182 0 +61 158 0 +62 157 0 +63 136 0 +64 150 0 +65 151 0 +66 134 0 +67 135 0 +68 149 0 +69 58 0 +70 238 0 +71 155 0 +72 222 0 +73 220 0 +74 81 0 +75 85 0 +76 79 0 +77 206 0 +78 204 0 +79 200 0 +80 18 0 +81 132 0 +82 133 0 +83 162 0 +84 143 0 +85 131 0 +86 146 0 +87 147 0 +88 44 0 +89 160 0 +90 19 0 +91 202 0 +92 199 0 +93 197 0 +94 207 0 +95 203 0 +96 45 0 +97 198 0 +98 174 0 +99 148 0 +100 163 0 +101 164 0 +102 165 0 +103 80 0 +104 193 0 +105 42 0 +106 138 0 +107 130 0 +108 77 0 +109 78 0 +110 98 0 +111 97 0 +112 87 0 +113 95 0 +114 94 0 +115 93 0 +116 86 0 +117 83 0 +118 84 0 +119 104 0 +120 103 0 +121 102 0 +122 101 0 +123 100 0 +124 99 0 +125 90 0 +126 91 0 From 2134fb766fe611a3e9a1373c8dcd78abd06f7ce6 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 03:45:21 -0600 Subject: [PATCH 40/75] More configurable --- sbndcode/CRT/CRTEventDisplay/build_tex.sh | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/sbndcode/CRT/CRTEventDisplay/build_tex.sh b/sbndcode/CRT/CRTEventDisplay/build_tex.sh index decfbc43e..ae6473d55 100644 --- a/sbndcode/CRT/CRTEventDisplay/build_tex.sh +++ b/sbndcode/CRT/CRTEventDisplay/build_tex.sh @@ -3,8 +3,16 @@ gdml=$2 author=$3 email=$4 edition=$5 +basedir=$6 -mkdir /exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/tex_work +echo $version +echo $gdml +echo $author +echo $email +echo $edition +echo $basedir + +mkdir ${basedir}/${edition}/tex_work echo "\documentclass{article} \usepackage[a4paper, margin=3cm]{geometry} @@ -20,7 +28,7 @@ wallnames=(Bottom South North West East "Top Low" "Top High") for wall in "${walls[@]}" do - list=$(ls /exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/${wall}_wall/*_front.pdf) + list=$(ls ${basedir}/${edition}/${wall}_wall/*_front.pdf) echo -n "\newcommand*{\\"$wall"ids}{" >> crt_channel_mapping_evds.tex for item in ${list} @@ -63,9 +71,9 @@ do \newpage \subsection{volCRTModule\x\_\x} \begin{center} - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ - \includegraphics[width=.85\textwidth]{/exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} + \includegraphics[width=.85\textwidth]{${basedir}/${edition}/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ + \includegraphics[width=.85\textwidth]{${basedir}/${edition}/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ + \includegraphics[width=.85\textwidth]{${basedir}/${edition}/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} \end{center} } \endgroup" >> crt_channel_mapping_evds.tex @@ -73,5 +81,5 @@ done echo "\end{document}" >> crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/tex_work crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory /exp/sbnd/data/users/hlay/crt_channel_mapping/${edition}/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory ${basedir}/${edition}/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory ${basedir}/${edition}/tex_work crt_channel_mapping_evds.tex From cc83f737e108ed8172fdc1eac2aa6843a470b823 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 03:45:48 -0600 Subject: [PATCH 41/75] Correctly name parameter --- sbndcode/CRT/CRTEventDisplay/crteventdisplayalg_sbnd.fcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbndcode/CRT/CRTEventDisplay/crteventdisplayalg_sbnd.fcl b/sbndcode/CRT/CRTEventDisplay/crteventdisplayalg_sbnd.fcl index 1a5f77633..0f7a523c8 100644 --- a/sbndcode/CRT/CRTEventDisplay/crteventdisplayalg_sbnd.fcl +++ b/sbndcode/CRT/CRTEventDisplay/crteventdisplayalg_sbnd.fcl @@ -99,7 +99,7 @@ crteventdisplayalg_sbnd_data.MaxTime: 1.5e6 crteventdisplayalg_sbnd_channel_mapping: @local::crteventdisplayalg_sbnd -crteventdisplayalg_sbnd_channel_mapping.DataMode: true +crteventdisplayalg_sbnd_channel_mapping.MC: false crteventdisplayalg_sbnd_channel_mapping.SaveRoot: false crteventdisplayalg_sbnd_channel_mapping.SaveViews: true From e20d6225d0c530c1e3550a15a1e747518bc9274e Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 03:51:01 -0600 Subject: [PATCH 42/75] Make consistent between fcl and bash script --- sbndcode/CRT/CRTEventDisplay/build_tex.sh | 18 ++++++++---------- ...run_crteventdisplay_channel_mapping_all.fcl | 17 ++++++++--------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/sbndcode/CRT/CRTEventDisplay/build_tex.sh b/sbndcode/CRT/CRTEventDisplay/build_tex.sh index ae6473d55..507aefd80 100644 --- a/sbndcode/CRT/CRTEventDisplay/build_tex.sh +++ b/sbndcode/CRT/CRTEventDisplay/build_tex.sh @@ -2,17 +2,15 @@ version=$1 gdml=$2 author=$3 email=$4 -edition=$5 -basedir=$6 +basedir=$5 echo $version echo $gdml echo $author echo $email -echo $edition echo $basedir -mkdir ${basedir}/${edition}/tex_work +mkdir ${basedir}/tex_work echo "\documentclass{article} \usepackage[a4paper, margin=3cm]{geometry} @@ -28,7 +26,7 @@ wallnames=(Bottom South North West East "Top Low" "Top High") for wall in "${walls[@]}" do - list=$(ls ${basedir}/${edition}/${wall}_wall/*_front.pdf) + list=$(ls ${basedir}/${wall}_wall/*_front.pdf) echo -n "\newcommand*{\\"$wall"ids}{" >> crt_channel_mapping_evds.tex for item in ${list} @@ -71,9 +69,9 @@ do \newpage \subsection{volCRTModule\x\_\x} \begin{center} - \includegraphics[width=.85\textwidth]{${basedir}/${edition}/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ - \includegraphics[width=.85\textwidth]{${basedir}/${edition}/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ - \includegraphics[width=.85\textwidth]{${basedir}/${edition}/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} + \includegraphics[width=.85\textwidth]{${basedir}/${walls[i]}_wall/volCRTModule\x_\x_front.pdf}\\\\ + \includegraphics[width=.85\textwidth]{${basedir}/${walls[i]}_wall/volCRTModule\x_\x_top.pdf}\\\\ + \includegraphics[width=.85\textwidth]{${basedir}/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} \end{center} } \endgroup" >> crt_channel_mapping_evds.tex @@ -81,5 +79,5 @@ done echo "\end{document}" >> crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory ${basedir}/${edition}/tex_work crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory ${basedir}/${edition}/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory ${basedir}/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory ${basedir}/tex_work crt_channel_mapping_evds.tex diff --git a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl index 435e34615..6da8eadc1 100644 --- a/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl +++ b/sbndcode/CRT/CRTEventDisplay/run_crteventdisplay_channel_mapping_all.fcl @@ -16,8 +16,7 @@ services: source: { module_type: RootInput - maxEvents: -1 - + maxEvents: -1 } physics: @@ -38,17 +37,17 @@ physics: end_paths: [ ana ] } -physics.analyzers.crtevdbot.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/bottom_wall" +physics.analyzers.crtevdbot.SaveDir: "/YOUR/DIRECTORY/NAME/bottom_wall" physics.analyzers.crtevdbot.EventDisplayConfig.ChosenTaggers: [ 0 ] -physics.analyzers.crtevdsou.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/south_wall" +physics.analyzers.crtevdsou.SaveDir: "/YOUR/DIRECTORY/NAME/south_wall" physics.analyzers.crtevdsou.EventDisplayConfig.ChosenTaggers: [ 1 ] -physics.analyzers.crtevdnor.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/north_wall" +physics.analyzers.crtevdnor.SaveDir: "/YOUR/DIRECTORY/NAME/north_wall" physics.analyzers.crtevdnor.EventDisplayConfig.ChosenTaggers: [ 2 ] -physics.analyzers.crtevdwes.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/west_wall" +physics.analyzers.crtevdwes.SaveDir: "/YOUR/DIRECTORY/NAME/west_wall" physics.analyzers.crtevdwes.EventDisplayConfig.ChosenTaggers: [ 3 ] -physics.analyzers.crtevdeas.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/east_wall" +physics.analyzers.crtevdeas.SaveDir: "/YOUR/DIRECTORY/NAME/east_wall" physics.analyzers.crtevdeas.EventDisplayConfig.ChosenTaggers: [ 4 ] -physics.analyzers.crtevdtpl.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/toplow_wall" +physics.analyzers.crtevdtpl.SaveDir: "/YOUR/DIRECTORY/NAME/toplow_wall" physics.analyzers.crtevdtpl.EventDisplayConfig.ChosenTaggers: [ 5 ] -physics.analyzers.crtevdtph.SaveDir: "/exp/sbnd/data/users/hlay/crt_channel_mapping/mar2025/tophigh_wall" +physics.analyzers.crtevdtph.SaveDir: "/YOUR/DIRECTORY/NAME/tophigh_wall" physics.analyzers.crtevdtph.EventDisplayConfig.ChosenTaggers: [ 6 ] From df8562a173b85d7630d5b065c50c92eecceba216 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 03:51:55 -0600 Subject: [PATCH 43/75] Include table for no inversion channel map --- sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl b/sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl index a34f136cd..16e96b3bc 100644 --- a/sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl +++ b/sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl @@ -5,4 +5,9 @@ crt_channel_map_sbnd: FileName: "SBNDCRTChannelMap_Commissioning_v5.txt" } +crt_channel_map_no_inversion: +{ + FileName: "SBNDCRTChannelMap_v5_no_inversion.txt" +} + END_PROLOG From 02dc0456bf359ccfac0548d149be8314a305a540 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 05:37:13 -0600 Subject: [PATCH 44/75] Ensure tex file is saved in correct area --- sbndcode/CRT/CRTEventDisplay/build_tex.sh | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sbndcode/CRT/CRTEventDisplay/build_tex.sh b/sbndcode/CRT/CRTEventDisplay/build_tex.sh index 507aefd80..235039478 100644 --- a/sbndcode/CRT/CRTEventDisplay/build_tex.sh +++ b/sbndcode/CRT/CRTEventDisplay/build_tex.sh @@ -19,7 +19,7 @@ echo "\documentclass{article} \usepackage[hidelinks]{hyperref} \title{SBND CRT Channel Mapping Displays \\\\ \vspace{1em} \small \textit{Produced using} \texttt{sbndcode ${version}} \textit{\&} \texttt{${gdml}}} -\author{${author} \\\\ \small ${email}}" > crt_channel_mapping_evds.tex +\author{${author} \\\\ \small ${email}}" > ${basedir}/tex_work/crt_channel_mapping_evds.tex walls=(bottom south north west east toplow tophigh) wallnames=(Bottom South North West East "Top Low" "Top High") @@ -27,17 +27,17 @@ wallnames=(Bottom South North West East "Top Low" "Top High") for wall in "${walls[@]}" do list=$(ls ${basedir}/${wall}_wall/*_front.pdf) - echo -n "\newcommand*{\\"$wall"ids}{" >> crt_channel_mapping_evds.tex + echo -n "\newcommand*{\\"$wall"ids}{" >> ${basedir}/tex_work/crt_channel_mapping_evds.tex for item in ${list} do name=$(echo $item | cut -d '/' -f 10) number=$(echo $name | cut -d '_' -f 2) - echo -n $number, >> crt_channel_mapping_evds.tex + echo -n $number, >> ${basedir}/tex_work/crt_channel_mapping_evds.tex done - sed -i '$ s/.$//' crt_channel_mapping_evds.tex - echo "}" >> crt_channel_mapping_evds.tex + sed -i '$ s/.$//' ${basedir}/tex_work/crt_channel_mapping_evds.tex + echo "}" >> ${basedir}/tex_work/crt_channel_mapping_evds.tex done echo "\begin{document} @@ -57,7 +57,7 @@ echo "\begin{document} \newpage \section{Explanation} This document contains a series of illustrations created using the \texttt{CRTEventDisplay} tool originally written by Tom Brooks \& heavily developed by myself. It shows the position of the various CRT modules according to the gdml file used in SBND simulation and reconstruction. The document is split into sections for the different tagger walls. For each module three illustrations are provided: front, top and side views. The axes show detector coordinates (X, Y and Z) and \`\`building coordinates\" (North, West and Up). The relevant module is shown in green. The TPCs are shown in grey in the centre for reference. The black outer is the full tagger wall. The thin grey are other modules in the wall. The red is the FEB position and the blue corresponds to the end of the FEB with channel 0 (the ethernet ports). -" >> crt_channel_mapping_evds.tex +" >> ${basedir}/tex_work/crt_channel_mapping_evds.tex for i in "${!walls[@]}" do @@ -74,10 +74,10 @@ do \includegraphics[width=.85\textwidth]{${basedir}/${walls[i]}_wall/volCRTModule\x_\x_side.pdf} \end{center} } -\endgroup" >> crt_channel_mapping_evds.tex +\endgroup" >> ${basedir}/tex_work/crt_channel_mapping_evds.tex done -echo "\end{document}" >> crt_channel_mapping_evds.tex +echo "\end{document}" >> ${basedir}/tex_work/crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory ${basedir}/tex_work crt_channel_mapping_evds.tex -pdflatex --shell-escape -output-directory ${basedir}/tex_work crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory ${basedir}/tex_work ${basedir}/tex_work/crt_channel_mapping_evds.tex +pdflatex --shell-escape -output-directory ${basedir}/tex_work ${basedir}/tex_work/crt_channel_mapping_evds.tex From 3ba37b53cd3e17178d3f7e09adfe0c832bcea61a Mon Sep 17 00:00:00 2001 From: nathanielerowe <70993723+nathanielerowe@users.noreply.github.com> Date: Thu, 19 Feb 2026 08:26:08 -0600 Subject: [PATCH 45/75] Update sbncode version to v10_14_02_03 --- ups/product_deps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ups/product_deps b/ups/product_deps index e21a2f2aa..38979aeb7 100644 --- a/ups/product_deps +++ b/ups/product_deps @@ -253,7 +253,7 @@ wpdir product_dir wire-cell-cfg # #################################### product version qual flags -sbncode v10_14_02_02 - +sbncode v10_14_02_03 - cetmodules v3_24_01 - only_for_build sbnd_data v01_42_00 - sbndutil v10_06_01 - optional From 029de7c21d910f5c27065335096cf609dd0b2c9d Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 07:35:03 -0600 Subject: [PATCH 46/75] Missing branch from CRTAnalysis --- sbndcode/CRT/CRTAna/CRTAnalysis_module.cc | 5 +++++ sbndcode/CRT/CRTAna/crtana_sbnd.fcl | 1 + 2 files changed, 6 insertions(+) diff --git a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc index 29f6614c9..08b1f8202 100644 --- a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc @@ -323,6 +323,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _tpc_end_dir_z; std::vector _tpc_length; std::vector _tpc_track_score; + std::vector _tpc_whichtpc; std::vector _tpc_truth_trackid; std::vector _tpc_truth_pdg; std::vector _tpc_truth_energy; @@ -621,6 +622,7 @@ sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) fTree->Branch("tpc_end_dir_z", "std::vector", &_tpc_end_dir_z); fTree->Branch("tpc_length", "std::vector", &_tpc_length); fTree->Branch("tpc_track_score", "std::vector", &_tpc_track_score); + fTree->Branch("tpc_whichtpc", "std::vector", &_tpc_whichtpc); fTree->Branch("tpc_sp_matched", "std::vector", &_tpc_sp_matched); fTree->Branch("tpc_sp_channel_set", "std::vector>", &_tpc_sp_channel_set); fTree->Branch("tpc_sp_xshift", "std::vector", &_tpc_sp_xshift); @@ -1682,6 +1684,7 @@ void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art:: _tpc_end_dir_z.resize(nTracks); _tpc_length.resize(nTracks); _tpc_track_score.resize(nTracks); + _tpc_whichtpc.resize(nTracks); _tpc_truth_trackid.resize(nTracks); _tpc_truth_pdg.resize(nTracks); _tpc_truth_energy.resize(nTracks); @@ -1771,6 +1774,7 @@ void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art:: const art::Ptr crttrack = tracksToTrackMatches.at(track.key()); const std::vector> trackHits = tracksToHits.at(track.key()); + _tpc_whichtpc[nActualTracks] = TPCGeoUtil::DetectedInTPC(trackHits); if(spacepoint.isNonnull()) { @@ -1915,6 +1919,7 @@ void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art:: _tpc_end_dir_z.resize(nActualTracks); _tpc_length.resize(nActualTracks); _tpc_track_score.resize(nActualTracks); + _tpc_whichtpc.resize(nActualTracks); _tpc_truth_trackid.resize(nActualTracks); _tpc_truth_pdg.resize(nActualTracks); _tpc_truth_energy.resize(nActualTracks); diff --git a/sbndcode/CRT/CRTAna/crtana_sbnd.fcl b/sbndcode/CRT/CRTAna/crtana_sbnd.fcl index f0a36b111..1ab588870 100644 --- a/sbndcode/CRT/CRTAna/crtana_sbnd.fcl +++ b/sbndcode/CRT/CRTAna/crtana_sbnd.fcl @@ -17,6 +17,7 @@ crtana_sbnd: crtana_data_sbnd: @local::crtana_sbnd crtana_data_sbnd.FEBDataModuleLabel: "crtdecoder" crtana_data_sbnd.DataMode: true +crtana_data_sbnd.NoTPC: false crtana_data_sbnd.HasPTB: true crtana_data_sbnd.HasTDC: true From b67448063cc0a9c20449afecf4640dbe9a11c8b3 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 07:53:20 -0600 Subject: [PATCH 47/75] Add ADRIFT - module for CRT calibration --- sbndcode/CRT/CRTAna/ADRIFT_module.cc | 1420 +++++++++++++++++++++++ sbndcode/CRT/CRTAna/CMakeLists.txt | 2 + sbndcode/CRT/CRTAna/adrift_sbnd.fcl | 31 + sbndcode/CRT/CRTAna/run_adrift_data.fcl | 28 + 4 files changed, 1481 insertions(+) create mode 100644 sbndcode/CRT/CRTAna/ADRIFT_module.cc create mode 100644 sbndcode/CRT/CRTAna/adrift_sbnd.fcl create mode 100644 sbndcode/CRT/CRTAna/run_adrift_data.fcl diff --git a/sbndcode/CRT/CRTAna/ADRIFT_module.cc b/sbndcode/CRT/CRTAna/ADRIFT_module.cc new file mode 100644 index 000000000..01727c94a --- /dev/null +++ b/sbndcode/CRT/CRTAna/ADRIFT_module.cc @@ -0,0 +1,1420 @@ +//////////////////////////////////////////////////////////////////////// +// Class: ADRIFT +// Plugin Type: analyzer +// File: ADRIFT_module.cc +// +// Author: Henry Lay (h.lay@sheffield.ac.uk) +// +// ADC +// Dynamic +// Range +// Improvement +// Facilitation +// Trees +//////////////////////////////////////////////////////////////////////// + +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" +#include "art/Framework/Principal/SubRun.h" +#include "canvas/Utilities/InputTag.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "art_root_io/TFileService.h" +#include "canvas/Persistency/Common/FindManyP.h" +#include "canvas/Persistency/Common/FindOneP.h" + +#include "TTree.h" +#include "TH1D.h" +#include "TF1.h" +#include "TFitResultPtr.h" +#include "TFitResult.h" +#include "TCanvas.h" +#include "TSystem.h" +#include "TStyle.h" +#include "TText.h" + +#include "artdaq-core/Data/RawEvent.hh" + +#include "sbnobj/SBND/CRT/FEBData.hh" +#include "sbnobj/SBND/CRT/CRTStripHit.hh" +#include "sbnobj/SBND/CRT/CRTCluster.hh" +#include "sbnobj/SBND/CRT/CRTSpacePoint.hh" +#include "sbnobj/SBND/CRT/CRTTrack.hh" + +#include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" +#include "sbndcode/ChannelMaps/CRT/CRTChannelMapService.h" + +namespace sbnd { + namespace crt { + class ADRIFT; + } +} + + +class sbnd::crt::ADRIFT : public art::EDAnalyzer { +public: + explicit ADRIFT(fhicl::ParameterSet const& p); + // The compiler-generated destructor is fine for non-base + // classes without bare pointers or other resource use. + + // Plugins should not be copied or assigned. + ADRIFT(ADRIFT const&) = delete; + ADRIFT(ADRIFT&&) = delete; + ADRIFT& operator=(ADRIFT const&) = delete; + ADRIFT& operator=(ADRIFT&&) = delete; + + // Required functions. + void analyze(art::Event const& e) override; + + // Selected optional functions. + void beginJob() override; + void endJob() override; + +private: + + void MakeSaveDirectories(art::Event const &e); + void AnalyseFEBDatas(art::Event const &e, const int window); + void AnalyseStripHits(art::Event const &e, const int window); + void AnalyseSpacePoints(art::Event const &e, const int window); + void AnalyseTracks(art::Event const &e, const int window); + void ProcessEntry(const int ch, const int window); + void PedestalFit(TH1D* hADC, double &fit, double &std, double &chi2, bool &converged, + bool badChannel, const int window); + void PedestalPeak(TH1D* hADC, double &peak); + void Rate(TH1D* hADC, double &rate, int window, double &period); + void PeakPeak(TH1D* hADC, const double &ped, double &peak); + void PeakFit(TH1D* hADC, const double &peak, const double &ped, double &fit, + double &chi2, bool &converged, bool badChannel, const int window); + double Saturation(TH1D* hADC); + void ResetVars(); + void SaveHist(TH1D *hADC, std::string &saveDir, std::string saveName, int rebin, bool badChannel); + static double LanGau(double *x, double *par); + + art::ServiceHandle fCRTGeoService; + + // Inputs + std::string fFEBDataModuleLabel, fCRTStripHitModuleLabel, fCRTClusterModuleLabel, + fCRTSpacePointModuleLabel, fCRTTrackModuleLabel, fDAQHeaderModuleLabel, fDAQHeaderInstanceLabel, + fTopSaveDirectory; + + bool fOnly2HitSpacePoints, fSaveAllFits, fSaveBadFits, fSaveSubset, fFEBs, fStripHits, fSpacePoints, + fTracks, fTrackLA, fSaveROOTHists, fAnalysePE; + + double fTrackAngleLimit, fPullWindow, fReconstructionWindow; + + uint32_t fRawTSCorrection; + + std::vector> fUnixWindows; + + // Other Global Parameters + std::vector fNEvents; + + TTree* fChannelTree; + + uint64_t _unix_start, _unix_end; + int _n_events, _channel, _gdml_id, _mac5, _raw_channel, _tagger, _channel_status; + double _area, _y_average, _ped_calib, _gain_calib, _ped_fit, _ped_fit_std, _ped_fit_chi2, _ped_peak, + _ped_reset_fit, _ped_reset_fit_std, _ped_reset_fit_chi2, _ped_reset_peak, _raw_max_chan_rate, _sh_rate, _sp_rate, _tr_rate, + _sh_peak_fit, _sh_peak_fit_chi2, _sh_peak_peak, _sh_pe_peak_fit, _sh_pe_peak_fit_chi2, _sh_pe_peak_peak, + _sh_sat_rate, _sh_sat_ratio_total, _sh_sat_ratio_peak, _sp_peak_fit, _sp_peak_fit_chi2, _sp_peak_peak, + _sp_pe_peak_fit, _sp_pe_peak_fit_chi2, _sp_pe_peak_peak, _sp_sat_rate, _sp_sat_ratio_total, _sp_sat_ratio_peak, + _tr_peak_fit, _tr_peak_fit_chi2, _tr_peak_peak, _tr_pe_peak_fit, _tr_pe_peak_fit_chi2, _tr_pe_peak_peak, + _tr_sat_rate, _tr_sat_ratio_total, _tr_sat_ratio_peak, _tr_lim_angle_peak_fit, _tr_lim_angle_peak_fit_chi2, _tr_lim_angle_peak_peak, + _tr_lim_angle_pe_peak_fit, _tr_lim_angle_pe_peak_fit_chi2, _tr_lim_angle_pe_peak_peak, _tr_lim_angle_sat_rate, + _tr_lim_angle_sat_ratio_total, _tr_lim_angle_sat_ratio_peak, _sh_ped_to_peak_fit, _sh_ped_reset_to_peak_fit, + _tr_by_length_peak_fit, _tr_by_length_peak_fit_chi2, _tr_by_length_peak_peak, + _tr_by_length_pe_peak_fit, _tr_by_length_pe_peak_fit_chi2, _tr_by_length_pe_peak_peak; + bool _horizontal, _ped_fit_converged, _ped_reset_fit_converged, _sh_peak_fit_converged, _sh_pe_peak_fit_converged, + _sp_peak_fit_converged, _sp_pe_peak_fit_converged, _tr_peak_fit_converged, _tr_pe_peak_fit_converged, _tr_lim_angle_peak_fit_converged, + _tr_lim_angle_pe_peak_fit_converged, _tr_by_length_peak_fit_converged, _tr_by_length_pe_peak_fit_converged; + + std::map> hADCPed, hADCPedReset, hADCMaxChan, hADCSH, hPESH, hADCSP, hPESP, hADCTr, hPETr, + hADCTrLA, hPETrLA, hADCTrByLength, hPETrByLength; + + std::map fPedestalSaveDirectory, fPedestalResetSaveDirectory, fPeakSaveDirectory, fBadPedestalSaveDirectory, + fBadPedestalResetSaveDirectory, fBadPeakSaveDirectory, fPedestalSubsetSaveDirectory, fPedestalResetSubsetSaveDirectory, + fStripHitSubsetSaveDirectory, fStripHitPESubsetSaveDirectory, fSpacePointSubsetSaveDirectory, fSpacePointPESubsetSaveDirectory, + fTrackSubsetSaveDirectory, fTrackPESubsetSaveDirectory, fTrackLASubsetSaveDirectory, fTrackLAPESubsetSaveDirectory, + fTrackByLengthSubsetSaveDirectory, fTrackByLengthPESubsetSaveDirectory; +}; + + +sbnd::crt::ADRIFT::ADRIFT(fhicl::ParameterSet const& p) + : EDAnalyzer{p} +{ + fFEBDataModuleLabel = p.get("FEBDataModuleLabel"); + fCRTStripHitModuleLabel = p.get("CRTStripHitModuleLabel"); + fCRTClusterModuleLabel = p.get("CRTClusterModuleLabel"); + fCRTSpacePointModuleLabel = p.get("CRTSpacePointModuleLabel"); + fCRTTrackModuleLabel = p.get("CRTTrackModuleLabel"); + fDAQHeaderModuleLabel = p.get("DAQHeaderModuleLabel"); + fDAQHeaderInstanceLabel = p.get("DAQHeaderInstanceLabel"); + fTopSaveDirectory = p.get("TopSaveDirectory"); + fOnly2HitSpacePoints = p.get("Only2HitSpacePoints"); + fSaveAllFits = p.get("SaveAllFits"); + fSaveBadFits = p.get("SaveBadFits"); + fSaveSubset = p.get("SaveSubset"); + fFEBs = p.get("FEBs"); + fStripHits = p.get("StripHits"); + fSpacePoints = p.get("SpacePoints"); + fTracks = p.get("Tracks"); + fTrackLA = p.get("TrackLA"); + fSaveROOTHists = p.get("SaveROOTHists"); + fAnalysePE = p.get("AnalysePE"); + fTrackAngleLimit = p.get("TrackAngleLimit"); + fPullWindow = p.get("PullWindow"); + fReconstructionWindow = p.get("ReconstructionWindow"); + fRawTSCorrection = p.get("RawTSCorrection"); + fUnixWindows = p.get>>("UnixWindows", { {0, std::numeric_limits::max()} }); + + art::ServiceHandle fs; + + fChannelTree = fs->make("channel_tree", ""); + fChannelTree->Branch("unix_start", &_unix_start); + fChannelTree->Branch("unix_end", &_unix_end); + fChannelTree->Branch("n_events", &_n_events); + fChannelTree->Branch("channel", &_channel); + fChannelTree->Branch("gdml_id", &_gdml_id); + fChannelTree->Branch("mac5", &_mac5); + fChannelTree->Branch("raw_channel", &_raw_channel); + fChannelTree->Branch("tagger", &_tagger); + fChannelTree->Branch("channel_status", &_channel_status); + fChannelTree->Branch("area", &_area); + fChannelTree->Branch("y_average", &_y_average); + fChannelTree->Branch("horizontal", &_horizontal); + fChannelTree->Branch("ped_calib", &_ped_calib); + fChannelTree->Branch("gain_calib", &_gain_calib); + if(fFEBs) + { + fChannelTree->Branch("ped_fit", &_ped_fit); + fChannelTree->Branch("ped_fit_std", &_ped_fit_std); + fChannelTree->Branch("ped_fit_chi2", &_ped_fit_chi2); + fChannelTree->Branch("ped_fit_converged", &_ped_fit_converged); + fChannelTree->Branch("ped_peak", &_ped_peak); + fChannelTree->Branch("ped_reset_fit", &_ped_reset_fit); + fChannelTree->Branch("ped_reset_fit_std", &_ped_reset_fit_std); + fChannelTree->Branch("ped_reset_fit_chi2", &_ped_reset_fit_chi2); + fChannelTree->Branch("ped_reset_fit_converged", &_ped_reset_fit_converged); + fChannelTree->Branch("ped_reset_peak", &_ped_reset_peak); + fChannelTree->Branch("raw_max_chan_rate", &_raw_max_chan_rate); + } + if(fStripHits) + { + fChannelTree->Branch("sh_rate", &_sh_rate); + fChannelTree->Branch("sh_peak_fit", &_sh_peak_fit); + fChannelTree->Branch("sh_peak_fit_chi2", &_sh_peak_fit_chi2); + fChannelTree->Branch("sh_peak_fit_converged", &_sh_peak_fit_converged); + fChannelTree->Branch("sh_peak_peak", &_sh_peak_peak); + fChannelTree->Branch("sh_sat_rate", &_sh_sat_rate); + fChannelTree->Branch("sh_sat_ratio_total", &_sh_sat_ratio_total); + fChannelTree->Branch("sh_sat_ratio_peak", &_sh_sat_ratio_peak); + fChannelTree->Branch("sh_ped_to_peak_fit", &_sh_ped_to_peak_fit); + fChannelTree->Branch("sh_ped_reset_to_peak_fit", &_sh_ped_reset_to_peak_fit); + + if(fAnalysePE) + { + fChannelTree->Branch("sh_pe_peak_fit", &_sh_pe_peak_fit); + fChannelTree->Branch("sh_pe_peak_fit_chi2", &_sh_pe_peak_fit_chi2); + fChannelTree->Branch("sh_pe_peak_fit_converged", &_sh_pe_peak_fit_converged); + fChannelTree->Branch("sh_pe_peak_peak", &_sh_pe_peak_peak); + } + } + if(fSpacePoints) + { + fChannelTree->Branch("sp_rate", &_sp_rate); + fChannelTree->Branch("sp_peak_fit", &_sp_peak_fit); + fChannelTree->Branch("sp_peak_fit_chi2", &_sp_peak_fit_chi2); + fChannelTree->Branch("sp_peak_fit_converged", &_sp_peak_fit_converged); + fChannelTree->Branch("sp_peak_peak", &_sp_peak_peak); + fChannelTree->Branch("sp_sat_rate", &_sp_sat_rate); + fChannelTree->Branch("sp_sat_ratio_total", &_sp_sat_ratio_total); + fChannelTree->Branch("sp_sat_ratio_peak", &_sp_sat_ratio_peak); + + if(fAnalysePE) + { + fChannelTree->Branch("sp_pe_peak_fit", &_sp_pe_peak_fit); + fChannelTree->Branch("sp_pe_peak_fit_chi2", &_sp_pe_peak_fit_chi2); + fChannelTree->Branch("sp_pe_peak_fit_converged", &_sp_pe_peak_fit_converged); + fChannelTree->Branch("sp_pe_peak_peak", &_sp_pe_peak_peak); + } + } + if(fTracks) + { + fChannelTree->Branch("tr_rate", &_tr_rate); + fChannelTree->Branch("tr_peak_fit", &_tr_peak_fit); + fChannelTree->Branch("tr_peak_fit_chi2", &_tr_peak_fit_chi2); + fChannelTree->Branch("tr_peak_fit_converged", &_tr_peak_fit_converged); + fChannelTree->Branch("tr_peak_peak", &_tr_peak_peak); + fChannelTree->Branch("tr_sat_rate", &_tr_sat_rate); + fChannelTree->Branch("tr_sat_ratio_total", &_tr_sat_ratio_total); + fChannelTree->Branch("tr_sat_ratio_peak", &_tr_sat_ratio_peak); + fChannelTree->Branch("tr_by_length_peak_fit", &_tr_by_length_peak_fit); + fChannelTree->Branch("tr_by_length_peak_fit_chi2", &_tr_by_length_peak_fit_chi2); + fChannelTree->Branch("tr_by_length_peak_fit_converged", &_tr_by_length_peak_fit_converged); + fChannelTree->Branch("tr_by_length_peak_peak", &_tr_by_length_peak_peak); + + if(fAnalysePE) + { + fChannelTree->Branch("tr_pe_peak_fit", &_tr_pe_peak_fit); + fChannelTree->Branch("tr_pe_peak_fit_chi2", &_tr_pe_peak_fit_chi2); + fChannelTree->Branch("tr_pe_peak_fit_converged", &_tr_pe_peak_fit_converged); + fChannelTree->Branch("tr_pe_peak_peak", &_tr_pe_peak_peak); + fChannelTree->Branch("tr_by_length_pe_peak_fit", &_tr_by_length_pe_peak_fit); + fChannelTree->Branch("tr_by_length_pe_peak_fit_chi2", &_tr_by_length_pe_peak_fit_chi2); + fChannelTree->Branch("tr_by_length_pe_peak_fit_converged", &_tr_by_length_pe_peak_fit_converged); + fChannelTree->Branch("tr_by_length_pe_peak_peak", &_tr_by_length_pe_peak_peak); + } + } + if(fTrackLA) + { + fChannelTree->Branch("tr_lim_angle_peak_fit", &_tr_lim_angle_peak_fit); + fChannelTree->Branch("tr_lim_angle_peak_fit_chi2", &_tr_lim_angle_peak_fit_chi2); + fChannelTree->Branch("tr_lim_angle_peak_fit_converged", &_tr_lim_angle_peak_fit_converged); + fChannelTree->Branch("tr_lim_angle_peak_peak", &_tr_lim_angle_peak_peak); + fChannelTree->Branch("tr_lim_angle_sat_rate", &_tr_lim_angle_sat_rate); + fChannelTree->Branch("tr_lim_angle_sat_ratio_total", &_tr_lim_angle_sat_ratio_total); + fChannelTree->Branch("tr_lim_angle_sat_ratio_peak", &_tr_lim_angle_sat_ratio_peak); + + if(fAnalysePE) + { + fChannelTree->Branch("tr_lim_angle_pe_peak_fit", &_tr_lim_angle_pe_peak_fit); + fChannelTree->Branch("tr_lim_angle_pe_peak_fit_chi2", &_tr_lim_angle_pe_peak_fit_chi2); + fChannelTree->Branch("tr_lim_angle_pe_peak_fit_converged", &_tr_lim_angle_pe_peak_fit_converged); + fChannelTree->Branch("tr_lim_angle_pe_peak_peak", &_tr_lim_angle_pe_peak_peak); + } + } + + for(uint window = 0; window < fUnixWindows.size(); ++window) + { + if(fSaveROOTHists) + { + for(int ch = 0; ch < 4480; ++ch) + { + if(fFEBs) + { + hADCPed[window][ch] = fs->make(Form("hADCPed_Window%i_Channel%i", window, ch), ";ADC;Readouts", 1000, -.5, 999.5); + hADCPedReset[window][ch] = fs->make(Form("hADCPedReset_Window%i_Channel%i", window, ch), ";ADC;Readouts", 1000, -.5, 999.5); + hADCMaxChan[window][ch] = fs->make(Form("hADCMaxChan_Window%i_Channel%i", window, ch), ";ADC;Readouts - Max Channel", 4300, -.5, 4299.5); + } + + if(fStripHits) + { + hADCSH[window][ch] = fs->make(Form("hADCSH_Window%i_Channel%i", window, ch), ";ADC;Strip Hits", 4300, -.5, 4299.5); + + if(fAnalysePE) + hPESH[window][ch] = fs->make(Form("hPESH_Window%i_Channel%i", window, ch), ";PE;Strip Hits", 4000, 0, 200); + } + + if(fSpacePoints) + { + hADCSP[window][ch] = fs->make(Form("hADCSP_Window%i_Channel%i", window, ch), ";ADC;Space Points", 4300, -.5, 4299.5); + + if(fAnalysePE) + hPESP[window][ch] = fs->make(Form("hPESP_Window%i_Channel%i", window, ch), ";PE;Space Points", 4000, 0, 200); + } + + if(fTracks) + { + hADCTr[window][ch] = fs->make(Form("hADCTr_Window%i_Channel%i", window, ch), ";ADC;Tracks", 4300, -.5, 4299.5); + hADCTrByLength[window][ch] = fs->make(Form("hADCTrByLength_Window%i_Channel%i", window, ch), ";ADC/Path Length;Tracks", 4300, -.5, 4299.5); + + if(fAnalysePE) + { + hPETr[window][ch] = fs->make(Form("hPETr_Window%i_Channel%i", window, ch), ";PE;Tracks", 4000, 0, 200); + hPETrByLength[window][ch] = fs->make(Form("hPETrByLength_Window%i_Channel%i", window, ch), ";PE/Path Length;Tracks", 4000, 0, 200); + } + } + + if(fTrackLA) + { + hADCTrLA[window][ch] = fs->make(Form("hADCTrLA_Window%i_Channel%i", window, ch), ";ADC;Tracks", 4300, -.5, 4299.5); + + if(fAnalysePE) + hPETrLA[window][ch] = fs->make(Form("hPETrLA_Window%i_Channel%i", window, ch), ";PE;Tracks", 4000, 0, 200); + } + } + } + else + { + for(int ch = 0; ch < 4480; ++ch) + { + if(fFEBs) + { + hADCPed[window][ch] = new TH1D(Form("hADCPed_Window%i_Channel%i", window, ch), ";ADC;Readouts", 1000, -.5, 999.5); + hADCPedReset[window][ch] = new TH1D(Form("hADCPedReset_Window%i_Channel%i", window, ch), ";ADC;Readouts", 1000, -.5, 999.5); + hADCMaxChan[window][ch] = new TH1D(Form("hADCMaxChan_Window%i_Channel%i", window, ch), ";ADC;Readouts - Max Channel", 4300, -.5, 4299.5); + } + + if(fStripHits) + { + hADCSH[window][ch] = new TH1D(Form("hADCSH_Window%i_Channel%i", window, ch), ";ADC;Strip Hits", 4300, -.5, 4299.5); + + if(fAnalysePE) + hPESH[window][ch] = new TH1D(Form("hPESH_Window%i_Channel%i", window, ch), ";PE;Strip Hits", 4000, 0, 200); + } + + if(fSpacePoints) + { + hADCSP[window][ch] = new TH1D(Form("hADCSP_Window%i_Channel%i", window, ch), ";ADC;Space Points", 4300, -.5, 4299.5); + + if(fAnalysePE) + hPESP[window][ch] = new TH1D(Form("hPESP_Window%i_Channel%i", window, ch), ";PE;Space Points", 4000, 0, 200); + } + + if(fTracks) + { + hADCTr[window][ch] = new TH1D(Form("hADCTr_Window%i_Channel%i", window, ch), ";ADC;Tracks", 4300, -.5, 4299.5); + hADCTrByLength[window][ch] = new TH1D(Form("hADCTrByLength_Window%i_Channel%i", window, ch), ";ADC/Path Length;Tracks", 4300, -.5, 4299.5); + + if(fAnalysePE) + { + hPETr[window][ch] = new TH1D(Form("hPETr_Window%i_Channel%i", window, ch), ";PE;Tracks", 4000, 0, 200); + hPETrByLength[window][ch] = new TH1D(Form("hPETrByLength_Window%i_Channel%i", window, ch), ";PE/Path Length;Tracks", 4000, 0, 200); + } + } + + if(fTrackLA) + { + hADCTrLA[window][ch] = new TH1D(Form("hADCTrLA_Window%i_Channel%i", window, ch), ";ADC;Tracks", 4300, -.5, 4299.5); + + if(fAnalysePE) + hPETrLA[window][ch] = new TH1D(Form("hPETrLA_Window%i_Channel%i", window, ch), ";PE;Tracks", 4000, 0, 200); + } + } + } + } + + for(uint i = 0; i < fUnixWindows.size(); ++i) + { + for(uint ii = i + 1; ii < fUnixWindows.size(); ++ii) + { + if(fUnixWindows[i].second > fUnixWindows[ii].first) + { + std::cout << "Unix windows overlap!" << std::endl; + throw std::exception(); + } + } + } +} + +void sbnd::crt::ADRIFT::analyze(art::Event const& e) +{ + // Get Raw TS + art::Handle DAQHeaderHandle; + e.getByLabel(fDAQHeaderModuleLabel, fDAQHeaderInstanceLabel, DAQHeaderHandle); + if(!DAQHeaderHandle.isValid()){ + std::cout << "RawEventHeader product " << fDAQHeaderModuleLabel << " - " << fDAQHeaderInstanceLabel << " not found..." << std::endl; + throw std::exception(); + } + artdaq::RawEvent rawHeaderEvent = artdaq::RawEvent(*DAQHeaderHandle); + uint64_t raw_ts = rawHeaderEvent.timestamp() - fRawTSCorrection; + + uint window = 0; + bool found = false; + + for(uint i = 0; i < fUnixWindows.size(); ++i) + { + if(raw_ts > fUnixWindows[i].first && raw_ts < fUnixWindows[i].second) + { + window = i; + found = true; + break; + } + } + + if(!found) + return; + + if(std::accumulate(fNEvents.begin(), fNEvents.end(), 0) == 0) + MakeSaveDirectories(e); + + if(fFEBs) + AnalyseFEBDatas(e, window); + + if(fStripHits) + AnalyseStripHits(e, window); + + if(fSpacePoints) + AnalyseSpacePoints(e, window); + + if(fTracks || fTrackLA) + AnalyseTracks(e, window); + + ++fNEvents[window]; +} + +void sbnd::crt::ADRIFT::MakeSaveDirectories(art::Event const &e) +{ + for(uint window = 0; window < fUnixWindows.size(); ++window) + { + std::string directory_structure = fUnixWindows.size() == 1 ? Form("run%i", e.run()) : Form("run%i/window%i", e.run(), window); + + if((fSaveAllFits || fSaveBadFits)) + { + gSystem->Exec(Form("mkdir -p %s", fTopSaveDirectory.c_str())); + + if(fFEBs) + { + fPedestalSaveDirectory[window] = Form("%s/%s/pedestals", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fPedestalSaveDirectory[window].c_str())); + + fPedestalResetSaveDirectory[window] = Form("%s/%s/pedestals_reset", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fPedestalResetSaveDirectory[window].c_str())); + + fBadPedestalSaveDirectory[window] = Form("%s/%s/pedestals/bad", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fBadPedestalSaveDirectory[window].c_str())); + + fBadPedestalResetSaveDirectory[window] = Form("%s/%s/pedestals_reset/bad", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fBadPedestalResetSaveDirectory[window].c_str())); + } + + if(fStripHits || fSpacePoints || fTracks || fTrackLA) + { + fPeakSaveDirectory[window] = Form("%s/%s/peaks", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fPeakSaveDirectory[window].c_str())); + + fBadPeakSaveDirectory[window] = Form("%s/%s/peaks/bad", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fBadPeakSaveDirectory[window].c_str())); + } + } + + if(fSaveSubset) + { + gSystem->Exec(Form("mkdir -p %s", fTopSaveDirectory.c_str())); + + if(fFEBs) + { + fPedestalSubsetSaveDirectory[window] = Form("%s/%s/subset/pedestals", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fPedestalSubsetSaveDirectory[window].c_str())); + + fPedestalResetSubsetSaveDirectory[window] = Form("%s/%s/subset/pedestals_reset", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fPedestalResetSubsetSaveDirectory[window].c_str())); + } + + if(fStripHits) + { + fStripHitSubsetSaveDirectory[window] = Form("%s/%s/subset/striphits", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fStripHitSubsetSaveDirectory[window].c_str())); + + if(fAnalysePE) + { + fStripHitPESubsetSaveDirectory[window] = Form("%s/%s/subset/striphits_pe", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fStripHitPESubsetSaveDirectory[window].c_str())); + } + } + + if(fSpacePoints) + { + fSpacePointSubsetSaveDirectory[window] = Form("%s/%s/subset/spacepoints", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fSpacePointSubsetSaveDirectory[window].c_str())); + + if(fAnalysePE) + { + fSpacePointPESubsetSaveDirectory[window] = Form("%s/%s/subset/spacepoints_pe", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fSpacePointPESubsetSaveDirectory[window].c_str())); + } + } + + if(fTracks) + { + fTrackSubsetSaveDirectory[window] = Form("%s/%s/subset/tracks", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fTrackSubsetSaveDirectory[window].c_str())); + + fTrackByLengthSubsetSaveDirectory[window] = Form("%s/%s/subset/tracks_by_length", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fTrackByLengthSubsetSaveDirectory[window].c_str())); + + if(fAnalysePE) + { + fTrackPESubsetSaveDirectory[window] = Form("%s/%s/subset/tracks_pe", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fTrackPESubsetSaveDirectory[window].c_str())); + + fTrackByLengthPESubsetSaveDirectory[window] = Form("%s/%s/subset/tracks_by_length_pe", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fTrackByLengthPESubsetSaveDirectory[window].c_str())); + } + } + + if(fTrackLA) + { + fTrackLASubsetSaveDirectory[window] = Form("%s/%s/subset/tracks_limited_angle", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fTrackLASubsetSaveDirectory[window].c_str())); + + if(fAnalysePE) + { + fTrackLAPESubsetSaveDirectory[window] = Form("%s/%s/subset/tracks_limited_angle_pe", fTopSaveDirectory.c_str(), directory_structure.c_str()); + gSystem->Exec(Form("mkdir -p %s", fTrackLAPESubsetSaveDirectory[window].c_str())); + } + } + } + } + + if((fSaveAllFits || fSaveBadFits || fSaveSubset)) + { + gStyle->SetOptStat(0); + gStyle->SetFrameLineWidth(2); + gStyle->SetTextFont(62); + gStyle->SetTextSize(0.07); + gStyle->SetLabelFont(62, "xyz"); + gStyle->SetLabelSize(0.05, "xyz"); + gStyle->SetTitleSize(0.05, "xyz"); + gStyle->SetTitleFont(62, "xyz"); + } +} + +void sbnd::crt::ADRIFT::AnalyseFEBDatas(art::Event const &e, const int window) +{ + // Get FEBDatas + art::Handle> FEBDataHandle; + e.getByLabel(fFEBDataModuleLabel, FEBDataHandle); + if(!FEBDataHandle.isValid()){ + std::cout << "FEBData product " << fFEBDataModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> FEBDataVec; + art::fill_ptr_vector(FEBDataVec, FEBDataHandle); + + // Get FEBData to CRTStripHit Assns + art::FindManyP febDatasToStripHits(FEBDataHandle, e, fCRTStripHitModuleLabel); + + for(const art::Ptr &feb_data : FEBDataVec) + { + const std::vector> strip_hits = febDatasToStripHits.at(feb_data.key()); + const uint m5 = feb_data->Mac5(); + const uint flags = feb_data->Flags(); + + std::set mask_channels; + + for(const art::Ptr &strip_hit : strip_hits) + { + mask_channels.insert(strip_hit->Channel()); + mask_channels.insert(strip_hit->Channel() + 1); + + if(strip_hit->Channel() % 2) + std::cout << "ODD Strip Hit Channel Number" << std::endl; + } + + int max_adc = -1, max_chan = -1; + + for(int i = 0; i < 32; ++i) + { + if(feb_data->ADC(i) > max_adc) + { + max_adc = feb_data->ADC(i); + max_chan = i; + } + + const int ch = m5 * 32 + i; + + if(!mask_channels.count(ch)) + hADCPed[window][ch]->Fill(feb_data->ADC(i)); + + if(flags != 1 && flags != 3) + hADCPedReset[window][ch]->Fill(feb_data->ADC(i)); + } + + if((flags == 1 || flags == 3) && max_chan != -1) + hADCMaxChan[window][m5 * 32 + max_chan]->Fill(feb_data->ADC(max_chan)); + } +} + +void sbnd::crt::ADRIFT::AnalyseStripHits(art::Event const &e, const int window) +{ + // Get CRTStripHits + art::Handle> CRTStripHitHandle; + e.getByLabel(fCRTStripHitModuleLabel, CRTStripHitHandle); + if(!CRTStripHitHandle.isValid()){ + std::cout << "CRTStripHit product " << fCRTStripHitModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTStripHitVec; + art::fill_ptr_vector(CRTStripHitVec, CRTStripHitHandle); + + for(const art::Ptr &strip_hit : CRTStripHitVec) + { + if(strip_hit->Channel() % 2) + std::cout << "ODD Strip Hit Channel Number" << std::endl; + + CRTSiPMGeo sipm1 = fCRTGeoService->GetSiPM(strip_hit->Channel()); + CRTSiPMGeo sipm2 = fCRTGeoService->GetSiPM(strip_hit->Channel() + 1); + + hADCSH[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() + sipm1.pedestal); + hADCSH[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() + sipm2.pedestal); + + if(fAnalysePE) + { + if((strip_hit->ADC1() + sipm1.pedestal) < 4089) + hPESH[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() * sipm1.gain); + if((strip_hit->ADC2() + sipm2.pedestal) < 4089) + hPESH[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() * sipm2.gain); + } + } +} + +void sbnd::crt::ADRIFT::AnalyseSpacePoints(art::Event const &e, const int window) +{ + // Get CRTSpacePoints + art::Handle> CRTSpacePointHandle; + e.getByLabel(fCRTSpacePointModuleLabel, CRTSpacePointHandle); + if(!CRTSpacePointHandle.isValid()){ + std::cout << "CRTSpacePoint product " << fCRTSpacePointModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTSpacePointVec; + art::fill_ptr_vector(CRTSpacePointVec, CRTSpacePointHandle); + + // Get CRTClusters + art::Handle> CRTClusterHandle; + e.getByLabel(fCRTClusterModuleLabel, CRTClusterHandle); + if(!CRTClusterHandle.isValid()){ + std::cout << "CRTCluster product " << fCRTClusterModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + // Get CRTSpacePoint to CRTCluster Assns + art::FindOneP spacepointsToClusters(CRTSpacePointHandle, e, fCRTSpacePointModuleLabel); + + // Get CRTCluster to CRTStripHit Assns + art::FindManyP clustersToStripHits(CRTClusterHandle, e, fCRTClusterModuleLabel); + + for(const art::Ptr &space_point : CRTSpacePointVec) + { + const art::Ptr cluster = spacepointsToClusters.at(space_point.key()); + + if(fOnly2HitSpacePoints && cluster->NHits() > 2) + continue; + + const std::vector> strip_hits = clustersToStripHits.at(cluster.key()); + + for(const art::Ptr &strip_hit : strip_hits) + { + if(strip_hit->Channel() % 2) + std::cout << "ODD Strip Hit Channel Number" << std::endl; + + CRTSiPMGeo sipm1 = fCRTGeoService->GetSiPM(strip_hit->Channel()); + CRTSiPMGeo sipm2 = fCRTGeoService->GetSiPM(strip_hit->Channel() + 1); + + hADCSP[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() + sipm1.pedestal); + hADCSP[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() + sipm2.pedestal); + + if(fAnalysePE) + { + if((strip_hit->ADC1() + sipm1.pedestal) < 4089) + hPESP[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() * sipm1.gain); + if((strip_hit->ADC2() + sipm2.pedestal) < 4089) + hPESP[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() * sipm2.gain); + } + } + } +} + +void sbnd::crt::ADRIFT::AnalyseTracks(art::Event const &e, const int window) +{ + // Get CRTTracks + art::Handle> CRTTrackHandle; + e.getByLabel(fCRTTrackModuleLabel, CRTTrackHandle); + if(!CRTTrackHandle.isValid()){ + std::cout << "CRTTrack product " << fCRTTrackModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTTrackVec; + art::fill_ptr_vector(CRTTrackVec, CRTTrackHandle); + + // Get CRTSpacePoints + art::Handle> CRTSpacePointHandle; + e.getByLabel(fCRTSpacePointModuleLabel, CRTSpacePointHandle); + if(!CRTSpacePointHandle.isValid()){ + std::cout << "CRTSpacePoint product " << fCRTSpacePointModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + // Get CRTClusters + art::Handle> CRTClusterHandle; + e.getByLabel(fCRTClusterModuleLabel, CRTClusterHandle); + if(!CRTClusterHandle.isValid()){ + std::cout << "CRTCluster product " << fCRTClusterModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + // Get CRTTrack to CRTSpacePoint Assns + art::FindManyP tracksToSpacePoints(CRTTrackHandle, e, fCRTTrackModuleLabel); + + // Get CRTSpacePoint to CRTCluster Assns + art::FindOneP spacepointsToClusters(CRTSpacePointHandle, e, fCRTSpacePointModuleLabel); + + // Get CRTCluster to CRTStripHit Assns + art::FindManyP clustersToStripHits(CRTClusterHandle, e, fCRTClusterModuleLabel); + + for(const art::Ptr &track : CRTTrackVec) + { + const std::vector> space_points = tracksToSpacePoints.at(track.key()); + + const geo::Vector_t tr_dir_vec = track->Direction(); + const TVector3 tr_dir = TVector3(tr_dir_vec.X(), tr_dir_vec.Y(), tr_dir_vec.Z()); + + for(const art::Ptr &space_point : space_points) + { + const art::Ptr cluster = spacepointsToClusters.at(space_point.key()); + + const std::vector> strip_hits = clustersToStripHits.at(cluster.key()); + const CRTTagger tagger = cluster->Tagger(); + TVector3 normal; + if(tagger == kBottomTagger || tagger == kTopLowTagger || tagger == kTopHighTagger) + normal = TVector3(0, 1, 0); + else if(tagger == kWestTagger || tagger == kEastTagger) + normal = TVector3(1, 0, 0); + else if(tagger == kSouthTagger || tagger == kNorthTagger) + normal = TVector3(0, 0, 1); + + const double angle = TMath::RadToDeg() * normal.Angle(tr_dir); + const double path_length = 1 / TMath::Cos(normal.Angle(tr_dir)); + + for(const art::Ptr &strip_hit : strip_hits) + { + if(strip_hit->Channel() % 2) + std::cout << "ODD Strip Hit Channel Number" << std::endl; + + CRTSiPMGeo sipm1 = fCRTGeoService->GetSiPM(strip_hit->Channel()); + CRTSiPMGeo sipm2 = fCRTGeoService->GetSiPM(strip_hit->Channel() + 1); + + if(fTracks) + { + hADCTr[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() + sipm1.pedestal); + hADCTr[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() + sipm2.pedestal); + + if(fAnalysePE) + { + if((strip_hit->ADC1() + sipm1.pedestal) < 4089) + hPETr[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() * sipm1.gain); + if((strip_hit->ADC2() + sipm2.pedestal) < 4089) + hPETr[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() * sipm2.gain); + } + + if((strip_hit->ADC1() + sipm1.pedestal) < 4089) + { + hADCTrByLength[window][strip_hit->Channel()]->Fill((strip_hit->ADC1() + sipm1.pedestal) / path_length); + + if(fAnalysePE && (strip_hit->ADC1() + sipm1.pedestal) < 4089) + hPETrByLength[window][strip_hit->Channel()]->Fill((strip_hit->ADC1() * sipm1.gain) / path_length); + } + if((strip_hit->ADC2() + sipm2.pedestal) < 4089) + { + hADCTrByLength[window][strip_hit->Channel() + 1]->Fill((strip_hit->ADC2() + sipm2.pedestal) / path_length); + + if(fAnalysePE && (strip_hit->ADC2() + sipm2.pedestal) < 4089) + hPETrByLength[window][strip_hit->Channel() + 1]->Fill((strip_hit->ADC2() * sipm2.gain) / path_length); + } + } + + if(fTrackLA && angle < fTrackAngleLimit) + { + hADCTrLA[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() + sipm1.pedestal); + hADCTrLA[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() + sipm2.pedestal); + + if(fAnalysePE) + { + if((strip_hit->ADC1() + sipm1.pedestal) < 4089) + hPETrLA[window][strip_hit->Channel()]->Fill(strip_hit->ADC1() * sipm1.gain); + if((strip_hit->ADC2() + sipm2.pedestal) < 4089) + hPETrLA[window][strip_hit->Channel() + 1]->Fill(strip_hit->ADC2() * sipm2.gain); + } + } + } + } + } +} + +void sbnd::crt::ADRIFT::beginJob() +{ + fNEvents = std::vector(fUnixWindows.size(), 0); +} + +void sbnd::crt::ADRIFT::endJob() +{ + art::ServiceHandle ChannelMapService; + + for(int gdml_i = 0; gdml_i < 140; ++gdml_i) + { + ResetVars(); + + std::cout << "=== Processing module " << gdml_i << std::endl; + + uint mac5 = ChannelMapService->GetMAC5FromOfflineModuleID(gdml_i); + bool invert = ChannelMapService->GetInversionFromOfflineModuleID(gdml_i); + + for(int ch_i = 0; ch_i < 32; ++ch_i) + { + const int ch = ChannelMapService->ConstructOfflineChannelIDFromOfflineModuleIDAndOfflineLocalChannel(gdml_i, ch_i); + + _channel = ch; + _gdml_id = gdml_i; + _mac5 = mac5; + _raw_channel = invert ? 31 - ch_i : ch_i; + _tagger = fCRTGeoService->ChannelToTaggerEnum(ch); + _channel_status = fCRTGeoService->GetSiPM(ch).status; + _area = fCRTGeoService->StripArea(ch); + _y_average = fCRTGeoService->StripAverageY(ch); + _ped_calib = fCRTGeoService->GetSiPM(ch).pedestal; + _gain_calib = fCRTGeoService->GetSiPM(ch).gain; + _horizontal = _tagger == kBottomTagger || _tagger == kTopLowTagger || _tagger == kTopHighTagger; + + for(uint window = 0; window < fUnixWindows.size(); ++window) + ProcessEntry(ch, window); + } + } +} + +void sbnd::crt::ADRIFT::ProcessEntry(const int ch, const int window) +{ + _unix_start = fUnixWindows[window].first; + _unix_end = fUnixWindows[window].second; + _n_events = fNEvents[window]; + + if(fSaveSubset && (ch > 1471 && ch < 1728)) + { + if(fFEBs) + { + SaveHist(hADCPed[window][ch], fPedestalSubsetSaveDirectory[window], Form("pedestal_channel_%i", ch), 2, _channel_status); + SaveHist(hADCPedReset[window][ch], fPedestalResetSubsetSaveDirectory[window], Form("pedestal_reset_channel_%i", ch), 2, _channel_status); + } + + if(fStripHits) + { + SaveHist(hADCSH[window][ch], fStripHitSubsetSaveDirectory[window], Form("strip_hit_channel_%i", ch), 20, _channel_status); + + if(fAnalysePE) + SaveHist(hPESH[window][ch], fStripHitPESubsetSaveDirectory[window], Form("strip_hit_pe_channel_%i", ch), 20, _channel_status); + } + + if(fSpacePoints) + { + SaveHist(hADCSP[window][ch], fSpacePointSubsetSaveDirectory[window], Form("space_point_channel_%i", ch), 20, _channel_status); + if(fAnalysePE) + SaveHist(hPESP[window][ch], fSpacePointPESubsetSaveDirectory[window], Form("space_point_pe_channel_%i", ch), 20, _channel_status); + } + + if(fTracks) + { + SaveHist(hADCTr[window][ch], fTrackSubsetSaveDirectory[window], Form("track_channel_%i", ch), 20, _channel_status); + SaveHist(hADCTrByLength[window][ch], fTrackByLengthSubsetSaveDirectory[window], Form("track_by_length_channel_%i", ch), 20, _channel_status); + if(fAnalysePE) + { + SaveHist(hPETr[window][ch], fTrackPESubsetSaveDirectory[window], Form("track_pe_channel_%i", ch), 20, _channel_status); + SaveHist(hPETrByLength[window][ch], fTrackByLengthPESubsetSaveDirectory[window], Form("track_by_length_pe_channel_%i", ch), 20, _channel_status); + } + } + + if(fTrackLA) + { + SaveHist(hADCTrLA[window][ch], fTrackLASubsetSaveDirectory[window], Form("track_limited_angle_channel_%i", ch), 20, _channel_status); + if(fAnalysePE) + SaveHist(hPETrLA[window][ch], fTrackLAPESubsetSaveDirectory[window], Form("track_limited_angle_pe_channel_%i", ch), 20, _channel_status); + } + + } + + if(fFEBs) + { + PedestalFit(hADCPed[window][ch], _ped_fit, _ped_fit_std, _ped_fit_chi2, _ped_fit_converged, _channel_status, window); + PedestalPeak(hADCPed[window][ch], _ped_peak); + + PedestalFit(hADCPedReset[window][ch], _ped_reset_fit, _ped_reset_fit_std, _ped_reset_fit_chi2, _ped_reset_fit_converged, _channel_status, window); + PedestalPeak(hADCPedReset[window][ch], _ped_reset_peak); + + Rate(hADCMaxChan[window][ch], _raw_max_chan_rate, window, fPullWindow); + } + + if(fStripHits) + { + Rate(hADCSH[window][ch], _sh_rate, window, fReconstructionWindow); + + PeakPeak(hADCSH[window][ch], _ped_calib, _sh_peak_peak); + PeakFit(hADCSH[window][ch], _sh_peak_peak, _ped_calib, _sh_peak_fit, _sh_peak_fit_chi2, _sh_peak_fit_converged, _channel_status, window); + _sh_ped_to_peak_fit = _sh_peak_fit - _ped_fit; + _sh_ped_reset_to_peak_fit = _sh_peak_fit - _ped_reset_fit; + + if(fAnalysePE) + { + PeakPeak(hPESH[window][ch], _ped_calib, _sh_pe_peak_peak); + PeakFit(hPESH[window][ch], _sh_pe_peak_peak, _ped_calib, _sh_pe_peak_fit, _sh_pe_peak_fit_chi2, _sh_pe_peak_fit_converged, _channel_status, window); + } + + const double sh_sat = Saturation(hADCSH[window][ch]); + _sh_sat_rate = sh_sat / (fNEvents[window] * fReconstructionWindow); + _sh_sat_ratio_total = sh_sat / hADCSH[window][ch]->GetEntries(); + _sh_sat_ratio_peak = sh_sat / hADCSH[window][ch]->GetBinContent(hADCSH[window][ch]->FindBin(_sh_peak_peak)); + } + + if(fSpacePoints) + { + Rate(hADCSP[window][ch], _sp_rate, window, fReconstructionWindow); + + PeakPeak(hADCSP[window][ch], _ped_calib, _sp_peak_peak); + PeakFit(hADCSP[window][ch], _sp_peak_peak, _ped_calib, _sp_peak_fit, _sp_peak_fit_chi2, _sp_peak_fit_converged, _channel_status, window); + + if(fAnalysePE) + { + PeakPeak(hPESP[window][ch], _ped_calib, _sp_pe_peak_peak); + PeakFit(hPESP[window][ch], _sp_pe_peak_peak, _ped_calib, _sp_pe_peak_fit, _sp_pe_peak_fit_chi2, _sp_pe_peak_fit_converged, _channel_status, window); + } + + const double sp_sat = Saturation(hADCSP[window][ch]); + _sp_sat_rate = sp_sat / (fNEvents[window] * fReconstructionWindow); + _sp_sat_ratio_total = sp_sat / hADCSP[window][ch]->GetEntries(); + _sp_sat_ratio_peak = sp_sat / hADCSP[window][ch]->GetBinContent(hADCSP[window][ch]->FindBin(_sp_peak_peak)); + } + + if(fTracks && _tagger != kBottomTagger) + { + Rate(hADCTr[window][ch], _tr_rate, window, fReconstructionWindow); + + PeakPeak(hADCTr[window][ch], _ped_calib, _tr_peak_peak); + PeakFit(hADCTr[window][ch], _tr_peak_peak, _ped_calib, _tr_peak_fit, _tr_peak_fit_chi2, _tr_peak_fit_converged, _channel_status, window); + + PeakPeak(hADCTrByLength[window][ch], _ped_calib, _tr_by_length_peak_peak); + PeakFit(hADCTrByLength[window][ch], _tr_by_length_peak_peak, _ped_calib, _tr_by_length_peak_fit, _tr_by_length_peak_fit_chi2, _tr_by_length_peak_fit_converged, _channel_status, window); + + if(fAnalysePE) + { + PeakPeak(hPETr[window][ch], _ped_calib, _tr_pe_peak_peak); + PeakFit(hPETr[window][ch], _tr_pe_peak_peak, _ped_calib, _tr_pe_peak_fit, _tr_pe_peak_fit_chi2, _tr_pe_peak_fit_converged, _channel_status, window); + + PeakPeak(hPETrByLength[window][ch], _ped_calib, _tr_by_length_pe_peak_peak); + PeakFit(hPETrByLength[window][ch], _tr_by_length_pe_peak_peak, _ped_calib, _tr_by_length_pe_peak_fit, _tr_by_length_pe_peak_fit_chi2, _tr_by_length_pe_peak_fit_converged, _channel_status, window); + } + + const double tr_sat = Saturation(hADCTr[window][ch]); + _tr_sat_rate = tr_sat / (fNEvents[window] * fReconstructionWindow); + _tr_sat_ratio_total = tr_sat / hADCTr[window][ch]->GetEntries(); + _tr_sat_ratio_peak = tr_sat / hADCTr[window][ch]->GetBinContent(hADCTr[window][ch]->FindBin(_tr_peak_peak)); + } + + if(fTrackLA && _tagger != kBottomTagger) + { + PeakPeak(hADCTrLA[window][ch], _ped_calib, _tr_lim_angle_peak_peak); + PeakFit(hADCTrLA[window][ch], _tr_lim_angle_peak_peak, _ped_calib, _tr_lim_angle_peak_fit, _tr_lim_angle_peak_fit_chi2, _tr_lim_angle_peak_fit_converged, _channel_status, window); + + if(fAnalysePE) + { + PeakPeak(hPETrLA[window][ch], _ped_calib, _tr_lim_angle_pe_peak_peak); + PeakFit(hPETrLA[window][ch], _tr_lim_angle_pe_peak_peak, _ped_calib, _tr_lim_angle_pe_peak_fit, _tr_lim_angle_pe_peak_fit_chi2, _tr_lim_angle_pe_peak_fit_converged, _channel_status, window); + } + + const double tr_lim_angle_sat = Saturation(hADCTrLA[window][ch]); + _tr_lim_angle_sat_rate = tr_lim_angle_sat / (fNEvents[window] * fReconstructionWindow); + _tr_lim_angle_sat_ratio_total = tr_lim_angle_sat / hADCTrLA[window][ch]->GetEntries(); + _tr_lim_angle_sat_ratio_peak = tr_lim_angle_sat / hADCTrLA[window][ch]->GetBinContent(hADCTrLA[window][ch]->FindBin(_tr_lim_angle_peak_peak)); + } + + fChannelTree->Fill(); +} + +void sbnd::crt::ADRIFT::PedestalFit(TH1D* hADC, double &fit, double &std, double &chi2, bool &converged, + bool badChannel, const int window) +{ + TF1 *gaus = new TF1("gaus", "gaus", 0, 500); + const TString name = hADC->GetName(); + TString ch_name = name; + TString type = ""; + + const int window_log = window == 0 ? 0 : std::floor(std::log10(window)); + + if(name.Contains("Reset")) + { + ch_name.Remove(0, 27 + window_log + 1); + type = "reset"; + } + else + ch_name.Remove(0,22 + window_log + 1); + + int ch = std::stoi(ch_name.Data()); + + TH1D* hADC2 = (TH1D*) hADC->Clone(name + "_for_fit"); + hADC2->Rebin(5); + + TFitResultPtr fit_result = hADC2->Fit(gaus, "QRS"); + converged = !(bool)(int(fit_result)); + + if(!converged && !badChannel) + std::cout << "Pedestal fit has not converged - " << hADC->GetName() << std::endl; + + fit = gaus->GetParameter("Mean"); + std = gaus->GetParameter("Sigma"); + chi2 = gaus->GetChisquare() / gaus->GetNDF(); + + if(fSaveAllFits || (fSaveBadFits && !converged) || (fSaveSubset && ch > 1471 && ch < 1728)) + { + TCanvas *c = new TCanvas(Form("c%s", name.Data()), Form("c%s", name.Data())); + c->cd(); + + hADC2->SetLineColor(kOrange+2); + hADC2->SetLineWidth(2); + hADC2->Draw("histe"); + gaus->SetLineColor(kSpring-6); + gaus->Draw("same"); + + if(badChannel) + { + TText *t = new TText(.5, .75, "Bad Channel"); + t->SetTextSize(0.1); + t->SetTextColor(kRed); + t->Draw(); + } + + if(converged) + { + if(type.Contains("reset")) + { + c->SaveAs(Form("%s/pedestal_reset_fit_channel_%s.png", fPedestalResetSaveDirectory[window].c_str(), ch_name.Data())); + c->SaveAs(Form("%s/pedestal_reset_fit_channel_%s.pdf", fPedestalResetSaveDirectory[window].c_str(), ch_name.Data())); + } + else + { + c->SaveAs(Form("%s/pedestal_fit_channel_%s.png", fPedestalSaveDirectory[window].c_str(), ch_name.Data())); + c->SaveAs(Form("%s/pedestal_fit_channel_%s.pdf", fPedestalSaveDirectory[window].c_str(), ch_name.Data())); + } + } + else + { + if(type.Contains("reset")) + { + c->SaveAs(Form("%s/pedestal_reset_fit_channel_%s.png", fBadPedestalResetSaveDirectory[window].c_str(), ch_name.Data())); + c->SaveAs(Form("%s/pedestal_reset_fit_channel_%s.pdf", fBadPedestalResetSaveDirectory[window].c_str(), ch_name.Data())); + } + else + { + c->SaveAs(Form("%s/pedestal_fit_channel_%s.png", fBadPedestalSaveDirectory[window].c_str(), ch_name.Data())); + c->SaveAs(Form("%s/pedestal_fit_channel_%s.pdf", fBadPedestalSaveDirectory[window].c_str(), ch_name.Data())); + } + } + } +} + +void sbnd::crt::ADRIFT::PedestalPeak(TH1D* hADC, double &peak) +{ + const int bin = hADC->GetMaximumBin(); + + peak = hADC->GetBinCenter(bin); +} + +void sbnd::crt::ADRIFT::Rate(TH1D* hADC, double &rate, int window, double &period) +{ + rate = hADC->GetEntries() / (fNEvents[window] * period); +} + +void sbnd::crt::ADRIFT::PeakPeak(TH1D* hist, const double &ped, double &peak) +{ + int bin = 0; + double max = std::numeric_limits::lowest(); + + const TString name = hist->GetName(); + + const int start = name.Contains("PE") ? 0 : (int)ped + 20; + + for(int i = start; i < 4000; ++i) + { + if(hist->GetBinContent(i) > max) + { + max = hist->GetBinContent(i); + bin = i; + } + } + + peak = hist->GetBinCenter(bin); +} + +void sbnd::crt::ADRIFT::PeakFit(TH1D* hist, const double &peak, const double &ped, double &fit, + double &chi2, bool &converged, bool badChannel, const int window) +{ + const TString name = hist->GetName(); + const bool pe = name.Contains("PE"); + TString ch_name = name; + TString type = ""; + + const double start = pe ? 0 : ped + 20; + const double end = pe ? 200 : 4000; + const double width = pe ? 0.25 : 10; + const double sigma = pe ? 1 : 50; + + TF1 *langau = new TF1("langau", LanGau, start, end, 4); + double params[4] = { width, peak, hist->GetEntries(), sigma }; + langau->SetParameters(params); + + const int window_log = window == 0 ? 0 : std::floor(std::log10(window)); + + if(name.Contains("SH")) + { + const int end = pe ? 20 + window_log + 1 : 21 + window_log + 1; + ch_name.Remove(0, end); + type = "strip_hit"; + } + else if(name.Contains("SP")) + { + const int end = pe ? 20 + window_log + 1 : 21 + window_log + 1; + ch_name.Remove(0, end); + type = "space_point"; + } + else if(name.Contains("TrLA")) + { + const int end = pe ? 22 + window_log + 1 : 23 + window_log + 1; + ch_name.Remove(0, end); + type = "track_limited_angle"; + } + else if(name.Contains("TrByLength")) + { + const int end = pe ? 28 + window_log + 1 : 29 + window_log + 1; + ch_name.Remove(0, end); + type = "track_by_length"; + } + else if(name.Contains("Tr")) + { + const int end = pe ? 20 + window_log + 1 : 21 + window_log + 1; + ch_name.Remove(0, end); + type = "track"; + } + else + std::cout << "Cannot identify histogram type (" << name << ")" << std::endl; + + int ch = std::stoi(ch_name.Data()); + + TH1D* hist2 = (TH1D*) hist->Clone(name + "_for_fit"); + hist2->Rebin(20); + + TFitResultPtr fit_result = hist2->Fit(langau, "QRS"); + converged = !(bool)(int(fit_result)); + + if(!converged && !badChannel) + std::cout << "Peak fit has not converged - " << hist->GetName() << std::endl; + + fit = langau->GetParameter(1); + chi2 = langau->GetChisquare() / langau->GetNDF(); + + if(fSaveAllFits || (fSaveBadFits && !converged) || (fSaveSubset && ch > 1471 && ch < 1728)) + { + TCanvas *c = new TCanvas(Form("c%s", name.Data()), Form("c%s", name.Data())); + c->cd(); + + hist2->SetLineColor(kOrange+2); + hist2->SetLineWidth(2); + hist2->Draw("histe"); + langau->SetLineColor(kSpring-6); + langau->Draw("same"); + + if(badChannel) + { + TText *t = new TText(.5, .75, "Bad Channel"); + t->SetTextSize(0.1); + t->SetTextColor(kRed); + t->Draw(); + } + + if(pe) + { + if(converged) + { + c->SaveAs(Form("%s/peak_fit_%s_pe_channel_%s.png", fPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + c->SaveAs(Form("%s/peak_fit_%s_pe_channel_%s.pdf", fPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + } + else + { + c->SaveAs(Form("%s/peak_fit_%s_pe_channel_%s.png", fBadPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + c->SaveAs(Form("%s/peak_fit_%s_pe_channel_%s.pdf", fBadPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + } + } + else + { + if(converged) + { + c->SaveAs(Form("%s/peak_fit_%s_channel_%s.png", fPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + c->SaveAs(Form("%s/peak_fit_%s_channel_%s.pdf", fPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + } + else + { + c->SaveAs(Form("%s/peak_fit_%s_channel_%s.png", fBadPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + c->SaveAs(Form("%s/peak_fit_%s_channel_%s.pdf", fBadPeakSaveDirectory[window].c_str(), type.Data(), ch_name.Data())); + } + } + } +} + +double sbnd::crt::ADRIFT::Saturation(TH1D* hADC) +{ + const double sat = hADC->GetBinContent(4090); + + for(int i = 4080; i < 4101; ++i) + { + if(i == 4090) + continue; + + if(hADC->GetBinContent(i) > sat) + std::cout << "Saturation appears to be in bin " << i << " (" << hADC->GetBinContent(i) + << ") not bin 4090 (" << sat << ")" << std::endl; + } + + return sat; +} + +void sbnd::crt::ADRIFT::ResetVars() +{ + _channel = std::numeric_limits::lowest(); + _gdml_id = std::numeric_limits::lowest(); + _mac5 = std::numeric_limits::lowest(); + _raw_channel = std::numeric_limits::lowest(); + _tagger = std::numeric_limits::lowest(); + _channel_status = std::numeric_limits::lowest(); + + _area = std::numeric_limits::lowest(); + _y_average = std::numeric_limits::lowest(); + _ped_calib = std::numeric_limits::lowest(); + _gain_calib = std::numeric_limits::lowest(); + _ped_fit = std::numeric_limits::lowest(); + _ped_fit_std = std::numeric_limits::lowest(); + _ped_fit_chi2 = std::numeric_limits::lowest(); + _ped_peak = std::numeric_limits::lowest(); + _ped_reset_fit = std::numeric_limits::lowest(); + _ped_reset_fit_std = std::numeric_limits::lowest(); + _ped_reset_fit_chi2 = std::numeric_limits::lowest(); + _ped_reset_peak = std::numeric_limits::lowest(); + _sh_rate = std::numeric_limits::lowest(); + _sp_rate = std::numeric_limits::lowest(); + _tr_rate = std::numeric_limits::lowest(); + _sh_peak_fit = std::numeric_limits::lowest(); + _sh_peak_fit_chi2 = std::numeric_limits::lowest(); + _sh_peak_peak = std::numeric_limits::lowest(); + _sh_sat_rate = std::numeric_limits::lowest(); + _sh_sat_ratio_total = std::numeric_limits::lowest(); + _sh_sat_ratio_peak = std::numeric_limits::lowest(); + _sh_ped_to_peak_fit = std::numeric_limits::lowest(); + _sh_ped_reset_to_peak_fit = std::numeric_limits::lowest(); + _sp_peak_fit = std::numeric_limits::lowest(); + _sp_peak_fit_chi2 = std::numeric_limits::lowest(); + _sp_peak_peak = std::numeric_limits::lowest(); + _sp_sat_rate = std::numeric_limits::lowest(); + _sp_sat_ratio_total = std::numeric_limits::lowest(); + _sp_sat_ratio_peak = std::numeric_limits::lowest(); + _tr_peak_fit = std::numeric_limits::lowest(); + _tr_peak_fit_chi2 = std::numeric_limits::lowest(); + _tr_peak_peak = std::numeric_limits::lowest(); + _tr_sat_rate = std::numeric_limits::lowest(); + _tr_sat_ratio_total = std::numeric_limits::lowest(); + _tr_sat_ratio_peak = std::numeric_limits::lowest(); + _tr_by_length_peak_fit = std::numeric_limits::lowest(); + _tr_by_length_peak_fit_chi2 = std::numeric_limits::lowest(); + _tr_by_length_peak_peak = std::numeric_limits::lowest(); + _tr_lim_angle_peak_fit = std::numeric_limits::lowest(); + _tr_lim_angle_peak_fit_chi2 = std::numeric_limits::lowest(); + _tr_lim_angle_peak_peak = std::numeric_limits::lowest(); + _tr_lim_angle_sat_rate = std::numeric_limits::lowest(); + _tr_lim_angle_sat_ratio_total = std::numeric_limits::lowest(); + _tr_lim_angle_sat_ratio_peak = std::numeric_limits::lowest(); + _sh_pe_peak_fit = std::numeric_limits::lowest(); + _sh_pe_peak_fit_chi2 = std::numeric_limits::lowest(); + _sh_pe_peak_peak = std::numeric_limits::lowest(); + _sp_pe_peak_fit = std::numeric_limits::lowest(); + _sp_pe_peak_fit_chi2 = std::numeric_limits::lowest(); + _sp_pe_peak_peak = std::numeric_limits::lowest(); + _tr_pe_peak_fit = std::numeric_limits::lowest(); + _tr_pe_peak_fit_chi2 = std::numeric_limits::lowest(); + _tr_pe_peak_peak = std::numeric_limits::lowest(); + _tr_by_length_pe_peak_fit = std::numeric_limits::lowest(); + _tr_by_length_pe_peak_fit_chi2 = std::numeric_limits::lowest(); + _tr_by_length_pe_peak_peak = std::numeric_limits::lowest(); + _tr_lim_angle_pe_peak_fit = std::numeric_limits::lowest(); + _tr_lim_angle_pe_peak_fit_chi2 = std::numeric_limits::lowest(); + _tr_lim_angle_pe_peak_peak = std::numeric_limits::lowest(); + + _horizontal = false; + _ped_fit_converged = false; + _ped_reset_fit_converged = false; + _sh_peak_fit_converged = false; + _sp_peak_fit_converged = false; + _tr_peak_fit_converged = false; + _tr_by_length_peak_fit_converged = false; + _tr_lim_angle_peak_fit_converged = false; + _sh_pe_peak_fit_converged = false; + _sp_pe_peak_fit_converged = false; + _tr_pe_peak_fit_converged = false; + _tr_by_length_pe_peak_fit_converged = false; + _tr_lim_angle_pe_peak_fit_converged = false; +} + +void sbnd::crt::ADRIFT::SaveHist(TH1D *hist, std::string &saveDir, std::string saveName, int rebin, bool badChannel) +{ + TCanvas *c = new TCanvas(Form("c%s", saveName.c_str()), Form("c%s", saveName.c_str())); + c->cd(); + + const TString name = hist->GetName(); + TH1D* hist2 = (TH1D*) hist->Clone(name + "_for_save"); + + hist2->SetLineColor(kOrange+2); + hist2->SetLineWidth(2); + hist2->Rebin(rebin); + hist2->Draw("histe"); + + if(badChannel) + { + TText *t = new TText(.5, .75, "Bad Channel"); + t->SetTextSize(0.1); + t->SetTextColor(kRed); + t->Draw(); + } + + c->SaveAs(Form("%s/%s.png", saveDir.c_str(), saveName.c_str())); + c->SaveAs(Form("%s/%s.pdf", saveDir.c_str(), saveName.c_str())); +} + +double sbnd::crt::ADRIFT::LanGau(double *x, double *par) +{ + //Fit parameters: + //par[0]=Width (scale) parameter of Landau density + //par[1]=Most Probable (MP, location) parameter of Landau density + //par[2]=Total area (integral -inf to inf, normalization constant) + //par[3]=Width (sigma) of convoluted Gaussian function + // + //In the Landau distribution (represented by the CERNLIB approximation), + //the maximum is located at x=-0.22278298 with the location parameter=0. + //This shift is corrected within this function, so that the actual + //maximum is identical to the MP parameter. + + // Numeric constants + double invsq2pi = 0.3989422804014; // (2 pi)^(-1/2) + double mpshift = -0.22278298; // Landau maximum location + + // Control constants + double np = 100.0; // number of convolution steps + double sc = 5.0; // convolution extends to +-sc Gaussian sigmas + + // Variables + double xx; + double mpc; + double fland; + double sum = 0.0; + double xlow,xupp; + double step; + double i; + + // MP shift correction + mpc = par[1] - mpshift * par[0]; + + // Range of convolution integral + xlow = x[0] - sc * par[3]; + xupp = x[0] + sc * par[3]; + + step = (xupp-xlow) / np; + + // Convolution integral of Landau and Gaussian by sum + for(i=1.0; i<=np/2; i++) { + xx = xlow + (i-.5) * step; + fland = TMath::Landau(xx,mpc,par[0]) / par[0]; + sum += fland * TMath::Gaus(x[0],xx,par[3]); + + xx = xupp - (i-.5) * step; + fland = TMath::Landau(xx,mpc,par[0]) / par[0]; + sum += fland * TMath::Gaus(x[0],xx,par[3]); + } + + return (par[2] * step * sum * invsq2pi / par[3]); +} + +DEFINE_ART_MODULE(sbnd::crt::ADRIFT) diff --git a/sbndcode/CRT/CRTAna/CMakeLists.txt b/sbndcode/CRT/CRTAna/CMakeLists.txt index 76a0241af..2cbcc6327 100644 --- a/sbndcode/CRT/CRTAna/CMakeLists.txt +++ b/sbndcode/CRT/CRTAna/CMakeLists.txt @@ -1,9 +1,11 @@ art_make( MODULE_LIBRARIES ROOT::Tree + ROOT::Graf3d art_root_io::TFileService_service larsim::Utils lardata::DetectorClocksService + sbndaq_artdaq_core::sbndaq-artdaq-core_Obj_SBND sbnobj::SBND_CRT sbnobj::SBND_Timing sbndcode_CRT_CRTBackTracker diff --git a/sbndcode/CRT/CRTAna/adrift_sbnd.fcl b/sbndcode/CRT/CRTAna/adrift_sbnd.fcl new file mode 100644 index 000000000..0be839450 --- /dev/null +++ b/sbndcode/CRT/CRTAna/adrift_sbnd.fcl @@ -0,0 +1,31 @@ +BEGIN_PROLOG + +adrift_data_sbnd: +{ + module_type: "ADRIFT" + FEBDataModuleLabel: "crtdecoder" + CRTStripHitModuleLabel: "crtstrips" + CRTClusterModuleLabel: "crtclustering" + CRTSpacePointModuleLabel: "crtspacepoints" + CRTTrackModuleLabel: "crttracks" + DAQHeaderModuleLabel: "daq" + DAQHeaderInstanceLabel: "RawEventHeader" + TopSaveDirectory: "/exp/sbnd/data/users/hlay/crt_comm_summer_2024/plots/adrift" + Only2HitSpacePoints: false + SaveAllFits: false + SaveBadFits: false + SaveSubset: false + FEBs: true + StripHits: true + SpacePoints: true + Tracks: true + TrackLA: true + SaveROOTHists: true + AnalysePE: false + TrackAngleLimit: 20 + PullWindow: 0.05 + ReconstructionWindow: 3.22e-3 + RawTSCorrection: 367000 +} + +END_PROLOG diff --git a/sbndcode/CRT/CRTAna/run_adrift_data.fcl b/sbndcode/CRT/CRTAna/run_adrift_data.fcl new file mode 100644 index 000000000..237978055 --- /dev/null +++ b/sbndcode/CRT/CRTAna/run_adrift_data.fcl @@ -0,0 +1,28 @@ +#include "services_sbnd.fcl" +#include "crt_services_sbnd.fcl" +#include "adrift_sbnd.fcl" + +process_name: ADRIFT + +services: +{ + TFileService: { fileName: "adrift_sbnd.root" } + @table::sbnd_basic_services + @table::crt_services_data_sbnd +} + +source: +{ + module_type: RootInput +} + +physics: +{ + analyzers: + { + adrift: @local::adrift_data_sbnd + } + + ana: [ adrift ] + end_paths: [ ana ] +} From 70411b58bddbd04c2d5a2f15a52b6f0f3ecc0129 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 07:58:38 -0600 Subject: [PATCH 48/75] Add CRTRateAnalysis - module for CRT real time rate analysis --- sbndcode/CRT/CRTAna/CRTRateAnalysis_module.cc | 292 ++++++++++++++++++ sbndcode/CRT/CRTAna/crtrateana_sbnd.fcl | 13 + sbndcode/CRT/CRTAna/run_crtrateana_data.fcl | 28 ++ 3 files changed, 333 insertions(+) create mode 100644 sbndcode/CRT/CRTAna/CRTRateAnalysis_module.cc create mode 100644 sbndcode/CRT/CRTAna/crtrateana_sbnd.fcl create mode 100644 sbndcode/CRT/CRTAna/run_crtrateana_data.fcl diff --git a/sbndcode/CRT/CRTAna/CRTRateAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTRateAnalysis_module.cc new file mode 100644 index 000000000..418c9c250 --- /dev/null +++ b/sbndcode/CRT/CRTAna/CRTRateAnalysis_module.cc @@ -0,0 +1,292 @@ +//////////////////////////////////////////////////////////////////////// +// Class: CRTRateAnalysis +// Plugin Type: analyzer (Unknown Unknown) +// File: CRTRateAnalysis_module.cc +// +// Generated at Tue Jan 7 05:28:06 2025 by Henry Lay using cetskelgen +// from cetlib version 3.18.02. +//////////////////////////////////////////////////////////////////////// + +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" +#include "art/Framework/Principal/SubRun.h" +#include "canvas/Utilities/InputTag.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "art_root_io/TFileService.h" + +#include "TTree.h" + +#include "canvas/Persistency/Common/FindOneP.h" +#include "canvas/Persistency/Common/FindManyP.h" + +#include "artdaq-core/Data/RawEvent.hh" + +#include "sbnobj/SBND/CRT/FEBData.hh" +#include "sbnobj/SBND/CRT/CRTSpacePoint.hh" +#include "sbnobj/SBND/CRT/CRTCluster.hh" +#include "sbnobj/SBND/CRT/CRTBlob.hh" + +#include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" +#include "sbndcode/ChannelMaps/CRT/CRTChannelMapService.h" + +namespace sbnd { + namespace crt { + class CRTRateAnalysis; + } +} + + +class sbnd::crt::CRTRateAnalysis : public art::EDAnalyzer { +public: + explicit CRTRateAnalysis(fhicl::ParameterSet const& p); + // The compiler-generated destructor is fine for non-base + // classes without bare pointers or other resource use. + + // Plugins should not be copied or assigned. + CRTRateAnalysis(CRTRateAnalysis const&) = delete; + CRTRateAnalysis(CRTRateAnalysis&&) = delete; + CRTRateAnalysis& operator=(CRTRateAnalysis const&) = delete; + CRTRateAnalysis& operator=(CRTRateAnalysis&&) = delete; + + // Required functions. + void analyze(art::Event const& e) override; + + void ResetEventVars(); + void ResetRawVars(); + void ResetSpacePointVars(); + void ResetBlobVars(); + +private: + + art::ServiceHandle fCRTGeoService; + art::ServiceHandle fCRTChannelMapService; + + std::string fFEBDataModuleLabel, fCRTSpacePointModuleLabel, + fCRTBlobModuleLabel, fDAQHeaderModuleLabel, fDAQHeaderInstanceLabel; + + TTree *fEventTree, *fRawTree, *fSpacePointTree, *fBlobTree; + + int32_t _run, _subrun, _event; + uint32_t _event_header_ts; + + int16_t _tagger, _module; + uint16_t _max_channel; + + int16_t _n_hits; + double _x, _y, _z, _pe; + + int16_t _n_total_sps, _n_bottom_sps, _n_bottom_sps_twohits, _n_south_sps, + _n_north_sps, _n_west_sps, _n_east_sps, _n_toplow_sps, _n_tophigh_sps; +}; + + +sbnd::crt::CRTRateAnalysis::CRTRateAnalysis(fhicl::ParameterSet const& p) + : EDAnalyzer{p} + , fFEBDataModuleLabel(p.get("FEBDataModuleLabel")) + , fCRTSpacePointModuleLabel(p.get("CRTSpacePointModuleLabel")) + , fCRTBlobModuleLabel(p.get("CRTBlobModuleLabel")) + , fDAQHeaderModuleLabel(p.get("DAQHeaderModuleLabel")) + , fDAQHeaderInstanceLabel(p.get("DAQHeaderInstanceLabel")) +{ + art::ServiceHandle fs; + + fEventTree = fs->make("events", ""); + fEventTree->Branch("run", &_run); + fEventTree->Branch("subrun", &_subrun); + fEventTree->Branch("event", &_event); + fEventTree->Branch("event_header_ts", &_event_header_ts); + + fRawTree = fs->make("readouts", ""); + fRawTree->Branch("run", &_run); + fRawTree->Branch("subrun", &_subrun); + fRawTree->Branch("event", &_event); + fRawTree->Branch("event_header_ts", &_event_header_ts); + fRawTree->Branch("tagger", &_tagger); + fRawTree->Branch("module", &_module); + fRawTree->Branch("max_channel", &_max_channel); + + fSpacePointTree = fs->make("spacepoints", ""); + fSpacePointTree->Branch("run", &_run); + fSpacePointTree->Branch("subrun", &_subrun); + fSpacePointTree->Branch("event", &_event); + fSpacePointTree->Branch("event_header_ts", &_event_header_ts); + fSpacePointTree->Branch("tagger", &_tagger); + fSpacePointTree->Branch("n_hits", &_n_hits); + fSpacePointTree->Branch("x", &_x); + fSpacePointTree->Branch("y", &_y); + fSpacePointTree->Branch("z", &_z); + fSpacePointTree->Branch("pe", &_pe); + + fBlobTree = fs->make("blobs", ""); + fBlobTree->Branch("run", &_run); + fBlobTree->Branch("subrun", &_subrun); + fBlobTree->Branch("event", &_event); + fBlobTree->Branch("event_header_ts", &_event_header_ts); + fBlobTree->Branch("n_total_sps", &_n_total_sps); + fBlobTree->Branch("n_bottom_sps", &_n_bottom_sps); + fBlobTree->Branch("n_bottom_sps_twohits", &_n_bottom_sps_twohits); + fBlobTree->Branch("n_south_sps", &_n_south_sps); + fBlobTree->Branch("n_north_sps", &_n_north_sps); + fBlobTree->Branch("n_west_sps", &_n_west_sps); + fBlobTree->Branch("n_east_sps", &_n_east_sps); + fBlobTree->Branch("n_toplow_sps", &_n_toplow_sps); + fBlobTree->Branch("n_tophigh_sps", &_n_tophigh_sps); + fBlobTree->Branch("pe", &_pe); +} + +void sbnd::crt::CRTRateAnalysis::analyze(art::Event const& e) +{ + ResetEventVars(); + + _run = e.id().run(); + _subrun = e.id().subRun(); + _event = e.id().event(); + + art::Handle DAQHeaderHandle; + e.getByLabel(fDAQHeaderModuleLabel, fDAQHeaderInstanceLabel, DAQHeaderHandle); + + if(DAQHeaderHandle.isValid()) + { + artdaq::RawEvent rawHeaderEvent = artdaq::RawEvent(*DAQHeaderHandle); + uint64_t raw_ts = rawHeaderEvent.timestamp(); + _event_header_ts = raw_ts / static_cast(1e9); + } + + fEventTree->Fill(); + + art::Handle> FEBDataHandle; + e.getByLabel(fFEBDataModuleLabel, FEBDataHandle); + + std::vector> FEBDataVec; + art::fill_ptr_vector(FEBDataVec, FEBDataHandle); + + for(auto const& data : FEBDataVec) + { + ResetRawVars(); + _tagger = fCRTGeoService->AuxDetIndexToTaggerEnum(data->Mac5()); + _module = data->Mac5(); + + int max_adc = -1, max_ch = -1; + + for(int ch = 0; ch < 32; ++ch) + { + int adc = data->ADC(ch); + + if(adc > max_adc) + { + max_adc = adc; + max_ch = ch; + } + } + + _max_channel = fCRTChannelMapService->ConstructOfflineChannelIDFromOfflineModuleIDAndOfflineLocalChannel(_module, max_ch); + + fRawTree->Fill(); + } + + art::Handle> CRTSpacePointHandle; + e.getByLabel(fCRTSpacePointModuleLabel, CRTSpacePointHandle); + + std::vector> CRTSpacePointVec; + art::fill_ptr_vector(CRTSpacePointVec, CRTSpacePointHandle); + + art::FindOneP spacePointsToClusters(CRTSpacePointHandle, e, fCRTSpacePointModuleLabel); + + for(auto const& spacePoint : CRTSpacePointVec) + { + ResetSpacePointVars(); + + const art::Ptr cluster = spacePointsToClusters.at(spacePoint.key()); + + _tagger = cluster->Tagger(); + _n_hits = cluster->NHits(); + _x = spacePoint->X(); + _y = spacePoint->Y(); + _z = spacePoint->Z(); + _pe = spacePoint->PE(); + + fSpacePointTree->Fill(); + } + + art::Handle> CRTBlobHandle; + e.getByLabel(fCRTBlobModuleLabel, CRTBlobHandle); + + std::vector> CRTBlobVec; + art::fill_ptr_vector(CRTBlobVec, CRTBlobHandle); + + art::FindManyP blobsToSpacePoints(CRTBlobHandle, e, fCRTBlobModuleLabel); + + for(auto const& blob : CRTBlobVec) + { + ResetBlobVars(); + + _n_total_sps = blob->TotalSpacePoints(); + _n_bottom_sps = blob->SpacePointsInTagger(kBottomTagger); + _n_south_sps = blob->SpacePointsInTagger(kSouthTagger); + _n_north_sps = blob->SpacePointsInTagger(kNorthTagger); + _n_west_sps = blob->SpacePointsInTagger(kWestTagger); + _n_east_sps = blob->SpacePointsInTagger(kEastTagger); + _n_toplow_sps = blob->SpacePointsInTagger(kTopLowTagger); + _n_tophigh_sps = blob->SpacePointsInTagger(kTopHighTagger); + _pe = blob->PE(); + + _n_bottom_sps_twohits = 0; + + const std::vector> spacePoints = blobsToSpacePoints.at(blob.key()); + + for(auto const& spacePoint : spacePoints) + { + const art::Ptr cluster = spacePointsToClusters.at(spacePoint.key()); + + if(cluster->Tagger() == kBottomTagger && cluster->NHits() > 1) + ++_n_bottom_sps_twohits; + } + + fBlobTree->Fill(); + } +} + +void sbnd::crt::CRTRateAnalysis::ResetEventVars() +{ + _run = -1; _subrun = -1; _event = -1; + _event_header_ts = std::numeric_limits::max(); +} + +void sbnd::crt::CRTRateAnalysis::ResetRawVars() +{ + _tagger = -1; _module = -1; + _max_channel = std::numeric_limits::max(); +} + +void sbnd::crt::CRTRateAnalysis::ResetSpacePointVars() +{ + _tagger = -1; + + _n_hits = -1; + + _x = std::numeric_limits::lowest(); + _y = std::numeric_limits::lowest(); + _z = std::numeric_limits::lowest(); + _pe = std::numeric_limits::lowest(); +} + +void sbnd::crt::CRTRateAnalysis::ResetBlobVars() +{ + _n_total_sps = -1; + _n_bottom_sps = -1; + _n_bottom_sps_twohits = -1; + _n_south_sps = -1; + _n_north_sps = -1; + _n_west_sps = -1; + _n_east_sps = -1; + _n_toplow_sps = -1; + _n_tophigh_sps = -1; + + _pe = std::numeric_limits::lowest(); +} + +DEFINE_ART_MODULE(sbnd::crt::CRTRateAnalysis) diff --git a/sbndcode/CRT/CRTAna/crtrateana_sbnd.fcl b/sbndcode/CRT/CRTAna/crtrateana_sbnd.fcl new file mode 100644 index 000000000..b9ffc2186 --- /dev/null +++ b/sbndcode/CRT/CRTAna/crtrateana_sbnd.fcl @@ -0,0 +1,13 @@ +BEGIN_PROLOG + +crtrateana_data_sbnd: +{ + FEBDataModuleLabel: "crtdecoder" + CRTSpacePointModuleLabel: "crtspacepoints" + CRTBlobModuleLabel: "crtblobs" + DAQHeaderModuleLabel: "daq" + DAQHeaderInstanceLabel: "RawEventHeader" + module_type: "CRTRateAnalysis" +} + +END_PROLOG diff --git a/sbndcode/CRT/CRTAna/run_crtrateana_data.fcl b/sbndcode/CRT/CRTAna/run_crtrateana_data.fcl new file mode 100644 index 000000000..b3c6f1c4e --- /dev/null +++ b/sbndcode/CRT/CRTAna/run_crtrateana_data.fcl @@ -0,0 +1,28 @@ +#include "services_sbnd.fcl" +#include "crt_services_sbnd.fcl" +#include "crtrateana_sbnd.fcl" + +process_name: CRTRateAnalysis + +services: +{ + @table::sbnd_basic_services + @table::crt_services_data_sbnd + TFileService: { fileName: "crtrateana_sbnd.root" } +} + +source: +{ + module_type: RootInput +} + +physics: +{ + analyzers: + { + crtrateana: @local::crtrateana_data_sbnd + } + + ana: [ crtrateana ] + end_paths: [ ana ] +} From a446e0ba31d7b8d4c6d2a0a444d83bee8ef55a74 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 08:10:50 -0600 Subject: [PATCH 49/75] Add CRTTopHatAnalysis - module for CRT beam top hat analysis --- .../CRT/CRTAna/CRTTopHatAnalysis_module.cc | 821 ++++++++++++++++++ sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl | 12 + sbndcode/CRT/CRTAna/run_crttophatana_data.fcl | 28 + 3 files changed, 861 insertions(+) create mode 100644 sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc create mode 100644 sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl create mode 100644 sbndcode/CRT/CRTAna/run_crttophatana_data.fcl diff --git a/sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc new file mode 100644 index 000000000..f338ce846 --- /dev/null +++ b/sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc @@ -0,0 +1,821 @@ +//////////////////////////////////////////////////////////////////////// +// Class: CRTTopHatAnalysis +// Plugin Type: analyzer +// File: CRTTopHatAnalysis_module.cc +// Author: Henry Lay (h.lay@sheffield.ac.uk) +//////////////////////////////////////////////////////////////////////// + +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" +#include "art/Framework/Principal/SubRun.h" +#include "canvas/Utilities/InputTag.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "art_root_io/TFileService.h" +#include "canvas/Persistency/Common/FindManyP.h" + +#include "TTree.h" + +#include "lardataobj/AnalysisBase/T0.h" +#include "lardataobj/RecoBase/Track.h" +#include "lardataobj/RecoBase/PFParticle.h" +#include "lardataobj/RecoBase/PFParticleMetadata.h" + +#include "larsim/Utils/TruthMatchUtils.h" +#include "lardata/DetectorInfoServices/DetectorClocksService.h" + +#include "sbndaq-artdaq-core/Obj/SBND/pmtSoftwareTrigger.hh" + +#include "sbnobj/SBND/CRT/FEBData.hh" +#include "sbnobj/SBND/CRT/CRTStripHit.hh" +#include "sbnobj/SBND/CRT/CRTCluster.hh" +#include "sbnobj/SBND/CRT/CRTSpacePoint.hh" +#include "sbnobj/SBND/CRT/CRTTrack.hh" +#include "sbnobj/SBND/Timing/DAQTimestamp.hh" + +#include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" +#include "sbndcode/Geometry/GeometryWrappers/TPCGeoAlg.h" +#include "sbndcode/CRT/CRTBackTracker/CRTBackTrackerAlg.h" +#include "sbndcode/CRT/CRTUtils/CRTCommonUtils.h" +#include "sbndcode/Decoders/PTB/sbndptb.h" +#include "sbndcode/Timing/SBNDRawTimingObj.h" + +namespace sbnd::crt { + class CRTTopHatAnalysis; +} + +class sbnd::crt::CRTTopHatAnalysis : public art::EDAnalyzer { +public: + explicit CRTTopHatAnalysis(fhicl::ParameterSet const& p); + // The compiler-generated destructor is fine for non-base + // classes without bare pointers or other resource use. + + // Plugins should not be copied or assigned. + CRTTopHatAnalysis(CRTTopHatAnalysis const&) = delete; + CRTTopHatAnalysis(CRTTopHatAnalysis&&) = delete; + CRTTopHatAnalysis& operator=(CRTTopHatAnalysis const&) = delete; + CRTTopHatAnalysis& operator=(CRTTopHatAnalysis&&) = delete; + + // Required functions. + void analyze(art::Event const& e) override; + + void AnalysePTBs(std::vector> &PTBVec); + + void AnalyseTDCs(std::vector> &TDCVec); + + void SortReferencing(); + + void AnalyseCRTStripHits(const art::Event &e, const std::vector> &CRTStripHitVec); + + void AnalyseCRTClusters(const art::Event &e, const std::vector> &CRTClusterVec, + const art::FindManyP &clustersToSpacePoints); + + void AnalyseCRTTracks(const art::Event &e, const std::vector> &CRTTrackVec); + + void AnalysePMTSoftwareTriggers(const art::Event &e, const std::vector> &PMTSoftwareTriggerVec); + + +private: + + art::ServiceHandle fCRTGeoService; + TPCGeoAlg fTPCGeoAlg; + + std::string fCRTStripHitModuleLabel, fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, + fCRTTrackModuleLabel, fPTBModuleLabel, fTDCModuleLabel, fTimingReferenceModuleLabel, + fPMTSoftwareTriggerModuleLabel; + bool fDebug, fCutT0, fSavePMTSoftwareTrigger; + double fMinT0, fMaxT0; + std::vector fAllowedPTBHLTs; + + TTree* fTree; + + // Tree variables + + int _run; + int _subrun; + int _event; + int _crt_timing_reference_type; + int _crt_timing_reference_channel; + + //strip hit to select the strip which has ADC above threshold + std::vector _sh_channel; + std::vector _sh_tagger; + std::vector _sh_ts0; + std::vector _sh_ts0_rwm_ref; + std::vector _sh_ts0_ptb_hlt_beam_gate_ref; + std::vector _sh_ts1; + std::vector _sh_ts1_rwm_ref; + std::vector _sh_ts1_ptb_hlt_beam_gate_ref; + std::vector _sh_unixs; + std::vector _sh_pos; + std::vector _sh_err; + std::vector _sh_adc1; + std::vector _sh_adc2; + std::vector _sh_saturated1; + std::vector _sh_saturated2; + std::vector _sh_truth_trackid; + std::vector _sh_truth_completeness; + std::vector _sh_truth_purity; + std::vector _sh_truth_pos; + std::vector _sh_truth_energy; + std::vector _sh_truth_time; + + //cluster from x-y coincidence for CRTSpacePoint + std::vector _cl_ts0; + std::vector _cl_ts0_rwm_ref; + std::vector _cl_ts0_ptb_hlt_beam_gate_ref; + std::vector _cl_ts1; + std::vector _cl_ts1_rwm_ref; + std::vector _cl_ts1_ptb_hlt_beam_gate_ref; + std::vector _cl_unixs; + std::vector _cl_nhits; + std::vector _cl_tagger; + std::vector _cl_composition; + std::vector _cl_has_sp; + std::vector _cl_sp_x; + std::vector _cl_sp_ex; + std::vector _cl_sp_y; + std::vector _cl_sp_ey; + std::vector _cl_sp_z; + std::vector _cl_sp_ez; + std::vector _cl_sp_pe; + std::vector _cl_sp_ts0; + std::vector _cl_sp_ts0_rwm_ref; + std::vector _cl_sp_ts0_ptb_hlt_beam_gate_ref; + std::vector _cl_sp_ets0; + std::vector _cl_sp_ts1; + std::vector _cl_sp_ts1_rwm_ref; + std::vector _cl_sp_ts1_ptb_hlt_beam_gate_ref; + std::vector _cl_sp_ets1; + std::vector _cl_sp_complete; + + //track level information + std::vector _tr_start_x; + std::vector _tr_start_y; + std::vector _tr_start_z; + std::vector _tr_end_x; + std::vector _tr_end_y; + std::vector _tr_end_z; + std::vector _tr_dir_x; + std::vector _tr_dir_y; + std::vector _tr_dir_z; + std::vector _tr_ts0; + std::vector _tr_ts0_rwm_ref; + std::vector _tr_ts0_ptb_hlt_beam_gate_ref; + std::vector _tr_ets0; + std::vector _tr_ts1; + std::vector _tr_ts1_rwm_ref; + std::vector _tr_ts1_ptb_hlt_beam_gate_ref; + std::vector _tr_ets1; + std::vector _tr_pe; + std::vector _tr_length; + std::vector _tr_tof; + std::vector _tr_theta; + std::vector _tr_phi; + std::vector _tr_triple; + std::vector _tr_tagger1; + std::vector _tr_tagger2; + std::vector _tr_tagger3; + + std::vector _ptb_hlt_trigger; + std::vector _ptb_hlt_timestamp; + + std::vector _ptb_llt_trigger; + std::vector _ptb_llt_timestamp; + + std::vector _tdc_channel; + std::vector _tdc_timestamp; + std::vector _tdc_offset; + std::vector _tdc_name; + + bool _etrig_good, _rwm_good, _ptb_hlt_beam_gate_good, _crt_t1_reset_good; + double _rwm_etrig_diff, _ptb_hlt_beam_gate_etrig_diff, _rwm_crt_t1_reset_diff, _ptb_hlt_beam_gate_crt_t1_reset_diff, + _rwm_ptb_hlt_beam_gate_diff; + + bool _pmt_st_found_trigger; + double _pmt_st_corrected_peak_time, _pmt_st_corrected_peak_time_rwm_ref; +}; + +sbnd::crt::CRTTopHatAnalysis::CRTTopHatAnalysis(fhicl::ParameterSet const& p) + : EDAnalyzer{p} +{ + fCRTStripHitModuleLabel = p.get("CRTStripHitModuleLabel", "crtstrips"); + fCRTClusterModuleLabel = p.get("CRTClusterModuleLabel", "crtclustering"); + fCRTSpacePointModuleLabel = p.get("CRTSpacePointModuleLabel", "crtspacepoints"); + fCRTTrackModuleLabel = p.get("CRTTrackModuleLabel", "crttracks"); + fPTBModuleLabel = p.get("PTBModuleLabel", "ptbdecoder"); + fTDCModuleLabel = p.get("TDCModuleLabel", "tdcdecoder"); + fTimingReferenceModuleLabel = p.get("TimingReferenceModuleLabel", "crtstrips"); + fPMTSoftwareTriggerModuleLabel = p.get("PMTSoftwareTriggerModuleLabel", "pmtmetricbnblight"); + fDebug = p.get("Debug", false); + fCutT0 = p.get("CutT0", false); + fSavePMTSoftwareTrigger = p.get("SavePMTSoftwareTrigger", false); + fMinT0 = p.get("MinT0", std::numeric_limits::min()); + fMaxT0 = p.get("MaxT0", std::numeric_limits::max()); + fAllowedPTBHLTs = p.get>("AllowedPTBHLTs", { 26, 27 }); + + art::ServiceHandle fs; + + fTree = fs->make("tree",""); + fTree->Branch("run", &_run); + fTree->Branch("subrun", &_subrun); + fTree->Branch("event", &_event); + fTree->Branch("crt_timing_reference_type", &_crt_timing_reference_type); + fTree->Branch("crt_timing_reference_channel", &_crt_timing_reference_channel); + + fTree->Branch("sh_channel", "std::vector", &_sh_channel); + fTree->Branch("sh_tagger", "std::vector", &_sh_tagger); + fTree->Branch("sh_ts0", "std::vector", &_sh_ts0); + fTree->Branch("sh_ts0_rwm_ref", "std::vector", &_sh_ts0_rwm_ref); + fTree->Branch("sh_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_sh_ts0_ptb_hlt_beam_gate_ref); + fTree->Branch("sh_ts1", "std::vector", &_sh_ts1); + fTree->Branch("sh_ts1_rwm_ref", "std::vector", &_sh_ts1_rwm_ref); + fTree->Branch("sh_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_sh_ts1_ptb_hlt_beam_gate_ref); + fTree->Branch("sh_unixs", "std::vector", &_sh_unixs); + fTree->Branch("sh_pos", "std::vector", &_sh_pos); + fTree->Branch("sh_err", "std::vector", &_sh_err); + fTree->Branch("sh_adc1", "std::vector", &_sh_adc1); + fTree->Branch("sh_adc2", "std::vector", &_sh_adc2); + fTree->Branch("sh_saturated1", "std::vector", &_sh_saturated1); + fTree->Branch("sh_saturated2", "std::vector", &_sh_saturated2); + + fTree->Branch("cl_ts0", "std::vector", &_cl_ts0); + fTree->Branch("cl_ts0_rwm_ref", "std::vector", &_cl_ts0_rwm_ref); + fTree->Branch("cl_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_cl_ts0_ptb_hlt_beam_gate_ref); + fTree->Branch("cl_ts1", "std::vector", &_cl_ts1); + fTree->Branch("cl_ts1_rwm_ref", "std::vector", &_cl_ts1_rwm_ref); + fTree->Branch("cl_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_cl_ts1_ptb_hlt_beam_gate_ref); + fTree->Branch("cl_unixs", "std::vector", &_cl_unixs); + fTree->Branch("cl_nhits", "std::vector", &_cl_nhits); + fTree->Branch("cl_tagger", "std::vector", &_cl_tagger); + fTree->Branch("cl_composition", "std::vector", &_cl_composition); + fTree->Branch("cl_has_sp", "std::vector", &_cl_has_sp); + fTree->Branch("cl_sp_x", "std::vector", &_cl_sp_x); + fTree->Branch("cl_sp_ex", "std::vector", &_cl_sp_ex); + fTree->Branch("cl_sp_y", "std::vector", &_cl_sp_y); + fTree->Branch("cl_sp_ey", "std::vector", &_cl_sp_ey); + fTree->Branch("cl_sp_z", "std::vector", &_cl_sp_z); + fTree->Branch("cl_sp_ez", "std::vector", &_cl_sp_ez); + fTree->Branch("cl_sp_pe", "std::vector", &_cl_sp_pe); + fTree->Branch("cl_sp_ts0", "std::vector", &_cl_sp_ts0); + fTree->Branch("cl_sp_ts0_rwm_ref", "std::vector", &_cl_sp_ts0_rwm_ref); + fTree->Branch("cl_sp_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_cl_sp_ts0_ptb_hlt_beam_gate_ref); + fTree->Branch("cl_sp_ets0", "std::vector", &_cl_sp_ets0); + fTree->Branch("cl_sp_ts1", "std::vector", &_cl_sp_ts1); + fTree->Branch("cl_sp_ts1_rwm_ref", "std::vector", &_cl_sp_ts1_rwm_ref); + fTree->Branch("cl_sp_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_cl_sp_ts1_ptb_hlt_beam_gate_ref); + fTree->Branch("cl_sp_ets1", "std::vector", &_cl_sp_ets1); + fTree->Branch("cl_sp_complete", "std::vector", &_cl_sp_complete); + + fTree->Branch("tr_start_x", "std::vector", &_tr_start_x); + fTree->Branch("tr_start_y", "std::vector", &_tr_start_y); + fTree->Branch("tr_start_z", "std::vector", &_tr_start_z); + fTree->Branch("tr_end_x", "std::vector", &_tr_end_x); + fTree->Branch("tr_end_y", "std::vector", &_tr_end_y); + fTree->Branch("tr_end_z", "std::vector", &_tr_end_z); + fTree->Branch("tr_dir_x", "std::vector", &_tr_dir_x); + fTree->Branch("tr_dir_y", "std::vector", &_tr_dir_y); + fTree->Branch("tr_dir_z", "std::vector", &_tr_dir_z); + fTree->Branch("tr_ts0", "std::vector", &_tr_ts0); + fTree->Branch("tr_ts0_rwm_ref", "std::vector", &_tr_ts0_rwm_ref); + fTree->Branch("tr_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_tr_ts0_ptb_hlt_beam_gate_ref); + fTree->Branch("tr_ets0", "std::vector", &_tr_ets0); + fTree->Branch("tr_ts1", "std::vector", &_tr_ts1); + fTree->Branch("tr_ts1_rwm_ref", "std::vector", &_tr_ts1_rwm_ref); + fTree->Branch("tr_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_tr_ts1_ptb_hlt_beam_gate_ref); + fTree->Branch("tr_ets1", "std::vector", &_tr_ets1); + fTree->Branch("tr_pe", "std::vector", &_tr_pe); + fTree->Branch("tr_length", "std::vector", &_tr_length); + fTree->Branch("tr_tof", "std::vector", &_tr_tof); + fTree->Branch("tr_theta", "std::vector", &_tr_theta); + fTree->Branch("tr_phi", "std::vector", &_tr_phi); + fTree->Branch("tr_triple", "std::vector", &_tr_triple); + fTree->Branch("tr_tagger1", "std::vector", &_tr_tagger1); + fTree->Branch("tr_tagger2", "std::vector", &_tr_tagger2); + fTree->Branch("tr_tagger3", "std::vector", &_tr_tagger3); + + fTree->Branch("ptb_hlt_trigger", "std::vector", &_ptb_hlt_trigger); + fTree->Branch("ptb_hlt_timestamp", "std::vector", &_ptb_hlt_timestamp); + fTree->Branch("ptb_llt_trigger", "std::vector", &_ptb_llt_trigger); + fTree->Branch("ptb_llt_timestamp", "std::vector", &_ptb_llt_timestamp); + + fTree->Branch("tdc_channel", "std::vector", &_tdc_channel); + fTree->Branch("tdc_timestamp", "std::vector", &_tdc_timestamp); + fTree->Branch("tdc_offset", "std::vector", &_tdc_offset); + fTree->Branch("tdc_name", "std::vector", &_tdc_name); + + fTree->Branch("etrig_good", &_etrig_good); + fTree->Branch("rwm_good", &_rwm_good); + fTree->Branch("ptb_hlt_beam_gate_good", &_ptb_hlt_beam_gate_good); + fTree->Branch("crt_t1_reset_good", &_crt_t1_reset_good); + fTree->Branch("rwm_etrig_diff", &_rwm_etrig_diff); + fTree->Branch("ptb_hlt_beam_gate_etrig_diff", &_ptb_hlt_beam_gate_etrig_diff); + fTree->Branch("rwm_crt_t1_reset_diff", &_rwm_crt_t1_reset_diff); + fTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fTree->Branch("rwm_ptb_hlt_beam_gate_diff", &_rwm_ptb_hlt_beam_gate_diff); + + if(fSavePMTSoftwareTrigger) + { + fTree->Branch("pmt_st_found_trigger", &_pmt_st_found_trigger); + fTree->Branch("pmt_st_corrected_peak_time", &_pmt_st_corrected_peak_time); + fTree->Branch("pmt_st_corrected_peak_time", &_pmt_st_corrected_peak_time); + fTree->Branch("pmt_st_corrected_peak_time_rwm_ref", &_pmt_st_corrected_peak_time_rwm_ref); + } +} + +void sbnd::crt::CRTTopHatAnalysis::analyze(art::Event const& e) +{ + _run = e.id().run(); + _subrun = e.id().subRun(); + _event = e.id().event(); + + _crt_timing_reference_type = -1; + _crt_timing_reference_channel = -1; + + art::Handle TimingReferenceHandle; + e.getByLabel(fTimingReferenceModuleLabel, TimingReferenceHandle); + if(TimingReferenceHandle.isValid()) + { + _crt_timing_reference_type = TimingReferenceHandle->timingType; + _crt_timing_reference_channel = TimingReferenceHandle->timingChannel; + } + + // Get PTBs + art::Handle> PTBHandle; + e.getByLabel(fPTBModuleLabel, PTBHandle); + if(!PTBHandle.isValid()){ + std::cout << "PTB product " << fPTBModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> PTBVec; + art::fill_ptr_vector(PTBVec, PTBHandle); + + // Fill PTB variables + AnalysePTBs(PTBVec); + + // Get TDCs + art::Handle> TDCHandle; + e.getByLabel(fTDCModuleLabel, TDCHandle); + if(!TDCHandle.isValid()){ + std::cout << "TDC product " << fTDCModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> TDCVec; + art::fill_ptr_vector(TDCVec, TDCHandle); + + // Fill TDC variables + AnalyseTDCs(TDCVec); + + SortReferencing(); + + // Get CRTStripHits + art::Handle> CRTStripHitHandle; + e.getByLabel(fCRTStripHitModuleLabel, CRTStripHitHandle); + if(!CRTStripHitHandle.isValid()){ + std::cout << "CRTStripHit product " << fCRTStripHitModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTStripHitVec; + art::fill_ptr_vector(CRTStripHitVec, CRTStripHitHandle); + + // Fill CRTStripHit variables + AnalyseCRTStripHits(e, CRTStripHitVec); + + // Get CRTClusters + art::Handle> CRTClusterHandle; + e.getByLabel(fCRTClusterModuleLabel, CRTClusterHandle); + if(!CRTClusterHandle.isValid()){ + std::cout << "CRTCluster product " << fCRTClusterModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTClusterVec; + art::fill_ptr_vector(CRTClusterVec, CRTClusterHandle); + + // Get CRTCluster to CRTSpacePoint Assns + art::FindManyP clustersToSpacePoints(CRTClusterHandle, e, fCRTSpacePointModuleLabel); + + // Fill CRTCluster variables + AnalyseCRTClusters(e, CRTClusterVec, clustersToSpacePoints); + + // Get CRTTracks + art::Handle> CRTTrackHandle; + e.getByLabel(fCRTTrackModuleLabel, CRTTrackHandle); + if(!CRTTrackHandle.isValid()){ + std::cout << "CRTTrack product " << fCRTTrackModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTTrackVec; + art::fill_ptr_vector(CRTTrackVec, CRTTrackHandle); + + // Fill CRTTrack variables + AnalyseCRTTracks(e, CRTTrackVec); + + if(fSavePMTSoftwareTrigger) + { + // Get PMTSoftwareTriggers + art::Handle> PMTSoftwareTriggerHandle; + e.getByLabel(fPMTSoftwareTriggerModuleLabel, PMTSoftwareTriggerHandle); + if(!PMTSoftwareTriggerHandle.isValid()){ + std::cout << "PMTSoftwareTrigger product " << fPMTSoftwareTriggerModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> PMTSoftwareTriggerVec; + art::fill_ptr_vector(PMTSoftwareTriggerVec, PMTSoftwareTriggerHandle); + + // Fill PMTSoftwareTrigger variables + AnalysePMTSoftwareTriggers(e, PMTSoftwareTriggerVec); + } + + fTree->Fill(); +} + +void sbnd::crt::CRTTopHatAnalysis::AnalysePTBs(std::vector> &PTBVec) +{ + unsigned nHLTs = 0; + + for(auto const& ptb : PTBVec) + nHLTs += ptb->GetNHLTriggers(); + + _ptb_hlt_trigger.resize(nHLTs); + _ptb_hlt_timestamp.resize(nHLTs); + + unsigned hlt_i = 0; + + for(auto const& ptb : PTBVec) + { + for(unsigned i = 0; i < ptb->GetNHLTriggers(); ++i) + { + _ptb_hlt_trigger[hlt_i] = ptb->GetHLTrigger(i).trigger_word; + _ptb_hlt_timestamp[hlt_i] = ptb->GetHLTrigger(i).timestamp * 20; + + ++hlt_i; + } + } + + unsigned nLLTs = 0; + + for(auto const& ptb : PTBVec) + nLLTs += ptb->GetNLLTriggers(); + + _ptb_llt_trigger.resize(nLLTs); + _ptb_llt_timestamp.resize(nLLTs); + + unsigned llt_i = 0; + + for(auto const& ptb : PTBVec) + { + for(unsigned i = 0; i < ptb->GetNLLTriggers(); ++i) + { + _ptb_llt_trigger[llt_i] = ptb->GetLLTrigger(i).trigger_word; + _ptb_llt_timestamp[llt_i] = ptb->GetLLTrigger(i).timestamp * 20; + + ++llt_i; + } + } +} + +void sbnd::crt::CRTTopHatAnalysis::AnalyseTDCs(std::vector> &TDCVec) +{ + const unsigned nTDCs = TDCVec.size(); + + _tdc_channel.resize(nTDCs); + _tdc_timestamp.resize(nTDCs); + _tdc_offset.resize(nTDCs); + _tdc_name.resize(nTDCs); + + unsigned tdc_i = 0; + + for(auto const& tdc : TDCVec) + { + _tdc_channel[tdc_i] = tdc->Channel(); + _tdc_timestamp[tdc_i] = tdc->Timestamp(); + _tdc_offset[tdc_i] = tdc->Offset(); + _tdc_name[tdc_i] = tdc->Name(); + + ++tdc_i; + } +} + +void sbnd::crt::CRTTopHatAnalysis::SortReferencing() +{ + _etrig_good = false; _rwm_good = false; _ptb_hlt_beam_gate_good = false; _crt_t1_reset_good = false; + _rwm_etrig_diff = std::numeric_limits::max(); _ptb_hlt_beam_gate_etrig_diff = std::numeric_limits::max(); + _rwm_crt_t1_reset_diff = std::numeric_limits::max(); _ptb_hlt_beam_gate_crt_t1_reset_diff = std::numeric_limits::max(); + _rwm_ptb_hlt_beam_gate_diff = std::numeric_limits::max(); + + int etrig_count = 0, etrig_id = -1, rwm_count = 0, rwm_id = -1, crt_t1_reset_count = 0, crt_t1_reset_id = -1; + + for(unsigned int tdc_i = 0; tdc_i < _tdc_channel.size(); ++tdc_i) + { + if(_tdc_channel[tdc_i] == 4) + { + ++etrig_count; + etrig_id = tdc_i; + } + else if(_tdc_channel[tdc_i] == 2) + { + ++rwm_count; + rwm_id = tdc_i; + } + else if(_tdc_channel[tdc_i] == 0) + { + ++crt_t1_reset_count; + crt_t1_reset_id = tdc_i; + } + } + + uint64_t etrig = std::numeric_limits::max(), rwm = std::numeric_limits::max(), + hlt = std::numeric_limits::max(), crt_t1_reset = std::numeric_limits::max(); + + if(etrig_count == 1) + { + _etrig_good = true; + etrig = _tdc_timestamp[etrig_id]; + } + + if(rwm_count == 1) + { + _rwm_good = true; + rwm = _tdc_timestamp[rwm_id]; + } + + if(etrig_count == 1) + { + double closest_diff = std::numeric_limits::max(); + + for(unsigned int ptb_i = 0; ptb_i < _ptb_hlt_trigger.size(); ++ptb_i) + { + std::bitset<32> hlt_bitmask = std::bitset<32>(_ptb_hlt_trigger[ptb_i]); + + for(uint32_t allowed_hlt : fAllowedPTBHLTs) + { + if(hlt_bitmask[allowed_hlt]) + { + _ptb_hlt_beam_gate_good = true; + + uint64_t temp_hlt = _ptb_hlt_timestamp[ptb_i]; + double diff = etrig > temp_hlt ? etrig - temp_hlt : -1. * (temp_hlt - etrig); + + if(std::abs(diff) < closest_diff) + { + closest_diff = diff; + hlt = temp_hlt; + } + } + } + } + } + + if(crt_t1_reset_count == 1) + { + _crt_t1_reset_good = true; + crt_t1_reset = _tdc_timestamp[crt_t1_reset_id]; + } + + if(_etrig_good && _rwm_good) + _rwm_etrig_diff = etrig > rwm ? etrig - rwm : -1. * (rwm - etrig); + + if(_etrig_good && _ptb_hlt_beam_gate_good) + _ptb_hlt_beam_gate_etrig_diff = etrig > hlt ? etrig - hlt : -1. * (hlt - etrig); + + if(_crt_t1_reset_good && _rwm_good) + _rwm_crt_t1_reset_diff = crt_t1_reset > rwm ? crt_t1_reset - rwm : -1. * (rwm - crt_t1_reset); + + if(_etrig_good && _crt_t1_reset_good && _ptb_hlt_beam_gate_good) + _ptb_hlt_beam_gate_crt_t1_reset_diff = crt_t1_reset > hlt ? crt_t1_reset - hlt : -1. * (hlt - crt_t1_reset); + + if(_etrig_good && _rwm_good && _ptb_hlt_beam_gate_good) + _rwm_ptb_hlt_beam_gate_diff = hlt > rwm ? hlt - rwm : -1. * (rwm - hlt); +} + +void sbnd::crt::CRTTopHatAnalysis::AnalyseCRTStripHits(const art::Event &e, const std::vector> &CRTStripHitVec) +{ + _sh_channel.clear(); + _sh_tagger.clear(); + _sh_ts0.clear(); + _sh_ts0_rwm_ref.clear(); + _sh_ts0_ptb_hlt_beam_gate_ref.clear(); + _sh_ts1.clear(); + _sh_ts1_rwm_ref.clear(); + _sh_ts1_ptb_hlt_beam_gate_ref.clear(); + _sh_unixs.clear(); + _sh_pos.clear(); + _sh_err.clear(); + _sh_adc1.clear(); + _sh_adc2.clear(); + _sh_saturated1.clear(); + _sh_saturated2.clear(); + + for(auto const &hit : CRTStripHitVec) + { + if(fCutT0 && (hit->Ts0() < fMinT0 || hit->Ts0() > fMaxT0)) + continue; + + _sh_channel.push_back(hit->Channel()); + _sh_tagger.push_back(fCRTGeoService->ChannelToTaggerEnum(hit->Channel())); + _sh_ts0.push_back(hit->Ts0()); + _sh_ts0_rwm_ref.push_back(hit->Ts0() + _rwm_etrig_diff); + _sh_ts0_ptb_hlt_beam_gate_ref.push_back(hit->Ts0() + _ptb_hlt_beam_gate_etrig_diff); + _sh_ts1.push_back(hit->Ts1()); + _sh_ts1_rwm_ref.push_back(hit->Ts1() + _rwm_crt_t1_reset_diff); + _sh_ts1_ptb_hlt_beam_gate_ref.push_back(hit->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); + _sh_unixs.push_back(hit->UnixS()); + _sh_pos.push_back(hit->Pos()); + _sh_err.push_back(hit->Error()); + _sh_adc1.push_back(hit->ADC1()); + _sh_adc2.push_back(hit->ADC2()); + _sh_saturated1.push_back(hit->Saturated1()); + _sh_saturated2.push_back(hit->Saturated2()); + } +} + +void sbnd::crt::CRTTopHatAnalysis::AnalyseCRTClusters(const art::Event &e, const std::vector> &CRTClusterVec, + const art::FindManyP &clustersToSpacePoints) +{ + _cl_ts0.clear(); + _cl_ts0_rwm_ref.clear(); + _cl_ts0_ptb_hlt_beam_gate_ref.clear(); + _cl_ts1.clear(); + _cl_ts1_rwm_ref.clear(); + _cl_ts1_ptb_hlt_beam_gate_ref.clear(); + _cl_unixs.clear(); + _cl_nhits.clear(); + _cl_tagger.clear(); + _cl_composition.clear(); + _cl_has_sp.clear(); + _cl_sp_x.clear(); + _cl_sp_ex.clear(); + _cl_sp_y.clear(); + _cl_sp_ey.clear(); + _cl_sp_z.clear(); + _cl_sp_ez.clear(); + _cl_sp_pe.clear(); + _cl_sp_ts0.clear(); + _cl_sp_ts0_rwm_ref.clear(); + _cl_sp_ts0_ptb_hlt_beam_gate_ref.clear(); + _cl_sp_ets0.clear(); + _cl_sp_ts1.clear(); + _cl_sp_ts1_rwm_ref.clear(); + _cl_sp_ts1_ptb_hlt_beam_gate_ref.clear(); + _cl_sp_ets1.clear(); + _cl_sp_complete.clear(); + + for(auto const &cluster : CRTClusterVec) + { + if(fCutT0 && (cluster->Ts0() < fMinT0 || cluster->Ts0() > fMaxT0)) + continue; + + _cl_ts0.push_back(cluster->Ts0()); + _cl_ts0_rwm_ref.push_back(cluster->Ts0() + _rwm_etrig_diff); + _cl_ts0_ptb_hlt_beam_gate_ref.push_back(cluster->Ts0() + _ptb_hlt_beam_gate_etrig_diff); + _cl_ts1.push_back(cluster->Ts1()); + _cl_ts1_rwm_ref.push_back(cluster->Ts1() + _rwm_crt_t1_reset_diff); + _cl_ts1_ptb_hlt_beam_gate_ref.push_back(cluster->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); + _cl_unixs.push_back(cluster->UnixS()); + _cl_nhits.push_back(cluster->NHits()); + _cl_tagger.push_back(cluster->Tagger()); + _cl_composition.push_back(cluster->Composition()); + + const auto spacepoints = clustersToSpacePoints.at(cluster.key()); + if(spacepoints.size() == 1) + { + const auto spacepoint = spacepoints[0]; + + _cl_has_sp.push_back(true); + _cl_sp_x.push_back(spacepoint->X()); + _cl_sp_ex.push_back(spacepoint->XErr()); + _cl_sp_y.push_back(spacepoint->Y()); + _cl_sp_ey.push_back(spacepoint->YErr()); + _cl_sp_z.push_back(spacepoint->Z()); + _cl_sp_ez.push_back(spacepoint->ZErr()); + _cl_sp_pe.push_back(spacepoint->PE()); + _cl_sp_ts0.push_back(spacepoint->Ts0()); + _cl_sp_ts0_rwm_ref.push_back(spacepoint->Ts0() + _rwm_etrig_diff); + _cl_sp_ts0_ptb_hlt_beam_gate_ref.push_back(spacepoint->Ts0() + _ptb_hlt_beam_gate_etrig_diff); + _cl_sp_ets0.push_back(spacepoint->Ts0Err()); + _cl_sp_ts1.push_back(spacepoint->Ts1()); + _cl_sp_ts1_rwm_ref.push_back(spacepoint->Ts1() + _rwm_crt_t1_reset_diff); + _cl_sp_ts1_ptb_hlt_beam_gate_ref.push_back(spacepoint->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); + _cl_sp_ets1.push_back(spacepoint->Ts1Err()); + _cl_sp_complete.push_back(spacepoint->Complete()); + } + else + { + _cl_has_sp.push_back(false); + _cl_sp_x.push_back(-999999.); + _cl_sp_ex.push_back(-999999.); + _cl_sp_y.push_back(-999999.); + _cl_sp_ey.push_back(-999999.); + _cl_sp_z.push_back(-999999.); + _cl_sp_ez.push_back(-999999.); + _cl_sp_pe.push_back(-999999.); + _cl_sp_ts0.push_back(-999999.); + _cl_sp_ts0_rwm_ref.push_back(-999999.); + _cl_sp_ts0_ptb_hlt_beam_gate_ref.push_back(-999999.); + _cl_sp_ets0.push_back(-999999.); + _cl_sp_ts1.push_back(-999999.); + _cl_sp_ts1_rwm_ref.push_back(-999999.); + _cl_sp_ts1_ptb_hlt_beam_gate_ref.push_back(-999999.); + _cl_sp_ets1.push_back(-999999.); + _cl_sp_complete.push_back(false); + } + } +} +void sbnd::crt::CRTTopHatAnalysis::AnalyseCRTTracks(const art::Event &e, const std::vector> &CRTTrackVec) +{ + _tr_start_x.clear(); + _tr_start_y.clear(); + _tr_start_z.clear(); + _tr_end_x.clear(); + _tr_end_y.clear(); + _tr_end_z.clear(); + _tr_dir_x.clear(); + _tr_dir_y.clear(); + _tr_dir_z.clear(); + _tr_ts0.clear(); + _tr_ts0_rwm_ref.clear(); + _tr_ts0_ptb_hlt_beam_gate_ref.clear(); + _tr_ets0.clear(); + _tr_ts1.clear(); + _tr_ts1_rwm_ref.clear(); + _tr_ts1_ptb_hlt_beam_gate_ref.clear(); + _tr_ets1.clear(); + _tr_pe.clear(); + _tr_length.clear(); + _tr_tof.clear(); + _tr_theta.clear(); + _tr_phi.clear(); + _tr_triple.clear(); + _tr_tagger1.clear(); + _tr_tagger2.clear(); + _tr_tagger3.clear(); + + for(auto const& track : CRTTrackVec) + { + if(fCutT0 && (track->Ts0() < fMinT0 || track->Ts0() > fMaxT0)) + continue; + + const geo::Point_t start = track->Start(); + _tr_start_x.push_back(start.X()); + _tr_start_y.push_back(start.Y()); + _tr_start_z.push_back(start.Z()); + + const geo::Point_t end = track->End(); + _tr_end_x.push_back(end.X()); + _tr_end_y.push_back(end.Y()); + _tr_end_z.push_back(end.Z()); + + const geo::Vector_t dir = track->Direction(); + _tr_dir_x.push_back(dir.X()); + _tr_dir_y.push_back(dir.Y()); + _tr_dir_z.push_back(dir.Z()); + + _tr_ts0.push_back(track->Ts0()); + _tr_ts0_rwm_ref.push_back(track->Ts0() + _rwm_etrig_diff); + _tr_ts0_ptb_hlt_beam_gate_ref.push_back(track->Ts0() + _ptb_hlt_beam_gate_etrig_diff); + _tr_ets0.push_back(track->Ts0Err()); + _tr_ts1.push_back(track->Ts1()); + _tr_ts1_rwm_ref.push_back(track->Ts1() + _rwm_crt_t1_reset_diff); + _tr_ts1_ptb_hlt_beam_gate_ref.push_back(track->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); + _tr_ets1.push_back(track->Ts1Err()); + _tr_pe.push_back(track->PE()); + _tr_length.push_back(track->Length()); + _tr_tof.push_back(track->ToF()); + _tr_theta.push_back(TMath::RadToDeg() * track->Theta()); + _tr_phi.push_back(TMath::RadToDeg() * track->Phi()); + _tr_triple.push_back(track->Triple()); + + unsigned tag_i = 0; + + for(auto const &tagger : track->Taggers()) + { + if(tag_i == 0) + _tr_tagger1.push_back(tagger); + else if(tag_i == 1) + _tr_tagger2.push_back(tagger); + else if(tag_i == 2) + _tr_tagger3.push_back(tagger); + + ++tag_i; + } + } +} + +void sbnd::crt::CRTTopHatAnalysis::AnalysePMTSoftwareTriggers(const art::Event &e, const std::vector> &PMTSoftwareTriggerVec) +{ + _pmt_st_found_trigger = false; + _pmt_st_corrected_peak_time = std::numeric_limits::lowest(); + _pmt_st_corrected_peak_time_rwm_ref = std::numeric_limits::lowest(); + + if(PMTSoftwareTriggerVec.size() != 1) + return; + + _pmt_st_found_trigger = PMTSoftwareTriggerVec[0]->foundBeamTrigger; + _pmt_st_corrected_peak_time = PMTSoftwareTriggerVec[0]->peaktime*1e3 + PMTSoftwareTriggerVec[0]->trig_ts; + _pmt_st_corrected_peak_time_rwm_ref = _pmt_st_corrected_peak_time + _rwm_ptb_hlt_beam_gate_diff; +} + +DEFINE_ART_MODULE(sbnd::crt::CRTTopHatAnalysis) diff --git a/sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl b/sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl new file mode 100644 index 000000000..a82b14e43 --- /dev/null +++ b/sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl @@ -0,0 +1,12 @@ +BEGIN_PROLOG + +crttophatana_data_sbnd: +{ + module_type: "CRTTopHatAnalysis" + CutT0: true + MinT0: -50000 + MaxT0: 50000 + SavePMTSoftwareTrigger: true +} + +END_PROLOG diff --git a/sbndcode/CRT/CRTAna/run_crttophatana_data.fcl b/sbndcode/CRT/CRTAna/run_crttophatana_data.fcl new file mode 100644 index 000000000..cce367369 --- /dev/null +++ b/sbndcode/CRT/CRTAna/run_crttophatana_data.fcl @@ -0,0 +1,28 @@ +#include "services_sbnd.fcl" +#include "crt_services_sbnd.fcl" +#include "crttophatana_sbnd.fcl" + +process_name: CRTTopHatAna + +services: +{ + TFileService: { fileName: "crttophatana_sbnd.root" } + @table::sbnd_basic_services + @table::crt_services_data_sbnd +} + +source: +{ + module_type: RootInput +} + +physics: +{ + analyzers: + { + crttophatana: @local::crttophatana_data_sbnd + } + + ana: [ crttophatana ] + end_paths: [ ana ] +} From c752a9148a7b92b38fcff9c3bfc6c8360df0ad88 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Mon, 23 Feb 2026 08:15:52 -0600 Subject: [PATCH 50/75] Add relevant functions for ADRIFT to GeoService --- .../Geometry/GeometryWrappers/CRTGeoService.h | 4 ++++ .../GeometryWrappers/CRTGeoService_service.cc | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/sbndcode/Geometry/GeometryWrappers/CRTGeoService.h b/sbndcode/Geometry/GeometryWrappers/CRTGeoService.h index 7b76b4fb0..c60b95b80 100644 --- a/sbndcode/Geometry/GeometryWrappers/CRTGeoService.h +++ b/sbndcode/Geometry/GeometryWrappers/CRTGeoService.h @@ -430,6 +430,10 @@ namespace sbnd::crt { bool IsPointInsideCRTLimits(const geo::Point_t &point); + double StripArea(const uint16_t channel); + + double StripAverageY(const uint16_t channel); + private: std::map fTaggers; diff --git a/sbndcode/Geometry/GeometryWrappers/CRTGeoService_service.cc b/sbndcode/Geometry/GeometryWrappers/CRTGeoService_service.cc index a8b64a01b..76be4b46f 100644 --- a/sbndcode/Geometry/GeometryWrappers/CRTGeoService_service.cc +++ b/sbndcode/Geometry/GeometryWrappers/CRTGeoService_service.cc @@ -562,6 +562,24 @@ namespace sbnd::crt { (point.Y() > lims[1] && point.Y() < lims[4]) && (point.Z() > lims[2] && point.Z() < lims[5]); } + + double CRTGeoService::StripArea(const uint16_t channel) + { + CRTStripGeo strip = GetStrip(channel); + const double x = abs(strip.maxX - strip.minX) / 2; + const double y = abs(strip.maxY - strip.minY) / 2; + const double z = abs(strip.maxZ - strip.minZ) / 2; + + // One will be 1cm so this gives the area in cm^2 + return x * y * z; + } + + double CRTGeoService::StripAverageY(const uint16_t channel) + { + CRTStripGeo strip = GetStrip(channel); + + return (strip.maxY + strip.minY) / 2; + } } DEFINE_ART_SERVICE(sbnd::crt::CRTGeoService) From 263176b4c4c419975ac68a6690febfe7e47d510d Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 24 Feb 2026 06:47:03 -0600 Subject: [PATCH 51/75] Add skeleton for timing analysis --- sbndcode/CRT/CRTAna/CMakeLists.txt | 1 + .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 666 ++++++++++++++++++ sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl | 19 + 3 files changed, 686 insertions(+) create mode 100644 sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc create mode 100644 sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl diff --git a/sbndcode/CRT/CRTAna/CMakeLists.txt b/sbndcode/CRT/CRTAna/CMakeLists.txt index 2cbcc6327..05de4d016 100644 --- a/sbndcode/CRT/CRTAna/CMakeLists.txt +++ b/sbndcode/CRT/CRTAna/CMakeLists.txt @@ -8,6 +8,7 @@ art_make( sbndaq_artdaq_core::sbndaq-artdaq-core_Obj_SBND sbnobj::SBND_CRT sbnobj::SBND_Timing + sbnobj::Common_Reco sbndcode_CRT_CRTBackTracker ) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc new file mode 100644 index 000000000..3fa9d0fd6 --- /dev/null +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -0,0 +1,666 @@ +//////////////////////////////////////////////////////////////////////// +// Class: CRTTimingAnalysis +// Plugin Type: analyzer +// File: CRTTimingAnalysis_module.cc +// Author: Henry Lay (h.lay@sheffield.ac.uk) +//////////////////////////////////////////////////////////////////////// + +#include "art/Framework/Core/EDAnalyzer.h" +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Principal/Run.h" +#include "art/Framework/Principal/SubRun.h" +#include "canvas/Utilities/InputTag.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "art_root_io/TFileService.h" +#include "canvas/Persistency/Common/FindManyP.h" +#include "canvas/Persistency/Common/FindOneP.h" + +#include "TTree.h" + +#include "lardataobj/RecoBase/Slice.h" +#include "lardataobj/RecoBase/PFParticle.h" +#include "lardataobj/RecoBase/Track.h" +#include "lardataobj/AnalysisBase/T0.h" + +#include "sbnobj/SBND/CRT/CRTStripHit.hh" +#include "sbnobj/SBND/CRT/CRTCluster.hh" +#include "sbnobj/SBND/CRT/CRTSpacePoint.hh" +#include "sbnobj/SBND/CRT/CRTTrack.hh" +#include "sbnobj/SBND/Timing/DAQTimestamp.hh" +#include "sbnobj/Common/Reco/CorrectedOpFlashTiming.h" + +#include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" +#include "sbndcode/Decoders/PTB/sbndptb.h" +#include "sbndcode/Timing/SBNDRawTimingObj.h" + +namespace sbnd::crt { + class CRTTimingAnalysis; +} + +class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { +public: + explicit CRTTimingAnalysis(fhicl::ParameterSet const& p); + // The compiler-generated destructor is fine for non-base + // classes without bare pointers or other resource use. + + // Plugins should not be copied or assigned. + CRTTimingAnalysis(CRTTimingAnalysis const&) = delete; + CRTTimingAnalysis(CRTTimingAnalysis&&) = delete; + CRTTimingAnalysis& operator=(CRTTimingAnalysis const&) = delete; + CRTTimingAnalysis& operator=(CRTTimingAnalysis&&) = delete; + + // Required functions. + void analyze(art::Event const& e) override; + + void AnalysePTBs(std::vector> &PTBVec); + + void AnalyseTDCs(std::vector> &TDCVec); + + void SortReferencing(); + + void AnalyseCRTSpacePoints(const std::vector> &CRTSpacePointVec, + const art::FindOneP &spacepointsToClusters, + const art::FindManyP &clustersToStripHits); + + void AnalyseCRTTracks(const std::vector> &CRTTrackVec, + const art::FindManyP &tracksToSpacePoints, + const art::FindOneP &spacepointsToClusters, + const art::FindManyP &clustersToStripHits); + + void AnalyseTPCSlices(const std::vector> &TPCSliceVec, + const art::FindManyP &sliceToCorrectedOpFlashes, + const art::FindManyP &sliceToPFPs, + const art::FindOneP &pfpToTrack, + const art::FindOneP &trackToCRTSpacePoint, + const art::FindOneP &spacepointsToClusters, + const art::FindManyP &clustersToStripHits); + +private: + + art::ServiceHandle fCRTGeoService; + + // fcl Controlled Variables + std::string fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, fCRTTrackModuleLabel, + fPTBModuleLabel, fTDCModuleLabel, fTimingReferenceModuleLabel, fTPCSliceModuleLabel, + fCorrectedOpFlashModuleLabel, fTPCTrackModuleLabel, fCRTSpacePointMatchingModuleLabel; + std::vector fAllowedPTBHLTs; + + // Global Storage + std::vector _ptb_hlt_trigger; + std::vector _ptb_hlt_timestamp; + + std::vector _ptb_llt_trigger; + std::vector _ptb_llt_timestamp; + + std::vector _tdc_channel; + std::vector _tdc_timestamp; + std::vector _tdc_offset; + std::vector _tdc_name; + + // Trees + TTree *fSPTree, *fTrTree, *fTPCTree; + + // Tree Variables + int _run; + int _subrun; + int _event; + int _crt_timing_reference_type; + int _crt_timing_reference_channel; + + bool _etrig_good; + bool _rwm_good; + bool _ptb_hlt_beam_gate_good; + bool _crt_t1_reset_good; + double _rwm_etrig_diff; + double _ptb_hlt_beam_gate_etrig_diff; + double _rwm_crt_t1_reset_diff; + double _ptb_hlt_beam_gate_crt_t1_reset_diff; + double _rwm_ptb_hlt_beam_gate_diff; + + uint16_t _sp_nhits; + int16_t _sp_tagger; + double _sp_x; + double _sp_y; + double _sp_z; + double _sp_pe; + double _sp_ts0; + double _sp_ts0_rwm_ref; + double _sp_ts0_ptb_hlt_beam_gate_ref; + double _sp_dts0; + double _sp_ts1; + double _sp_ts1_rwm_ref; + double _sp_ts1_ptb_hlt_beam_gate_ref; + double _sp_dts1; + bool _sp_single_timing_chain; + int16_t _sp_timing_chain; + std::vector _sp_sh_channel_set; + std::vector _sp_sh_mac5_set; + std::vector _sp_sh_timing_chain_set; + std::vector _sp_sh_ts0_set; + std::vector _sp_sh_ts1_set; + std::vector _sp_sh_time_walk_set; + std::vector _sp_sh_prop_delay_set; + std::vector _sp_sh_cable_length_set; + std::vector _sp_sh_calib_offset_ts0_set; + std::vector _sp_sh_calib_offset_ts1_set; + + double _tr_start_x; + double _tr_start_y; + double _tr_start_z; + double _tr_end_x; + double _tr_end_y; + double _tr_end_z; + double _tr_dir_x; + double _tr_dir_y; + double _tr_dir_z; + double _tr_ts0; + double _tr_ts0_rwm_ref; + double _tr_ts0_ptb_hlt_beam_gate_ref; + double _tr_ts1; + double _tr_ts1_rwm_ref; + double _tr_ts1_ptb_hlt_beam_gate_ref; + double _tr_pe; + double _tr_length; + double _tr_length_tof; + double _tr_tof_ts0; + double _tr_tof_diff_ts0; + double _tr_tof_ts1; + double _tr_tof_diff_ts1; + double _tr_theta; + double _tr_phi; + bool _tr_triple; + int16_t _tr_tagger1; + int16_t _tr_tagger2; + int16_t _tr_tagger3; + int16_t _tr_start_tagger; + double _tr_start_dts0; + bool _tr_start_single_timing_chain; + int16_t _tr_start_timing_chain; + int16_t _tr_end_tagger; + double _tr_end_dts0; + bool _tr_end_single_timing_chain; + int16_t _tr_end_timing_chain; + + bool _tpc_has_corrected_opflash; + bool _tpc_has_crt_sp_match; + double _tpc_opflash_t0; + double _tpc_opflash_nutof_light; + double _tpc_opflash_nutof_charge; + double _tpc_opflash_t0_corrected; + double _tpc_opflash_t0_corrected_rwm; + double _tpc_crt_sp_score; + double _tpc_crt_sp_ts0; + double _tpc_crt_sp_ts0_rwm_ref; + double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref; + double _tpc_crt_sp_dts0; + double _tpc_crt_sp_ts1; + double _tpc_crt_sp_ts1_rwm_ref; + double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref; + double _tpc_crt_sp_dts1; +}; + +sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) + : EDAnalyzer{p} +{ + fCRTClusterModuleLabel = p.get("CRTClusterModuleLabel"); + fCRTSpacePointModuleLabel = p.get("CRTSpacePointModuleLabel"); + fCRTTrackModuleLabel = p.get("CRTTrackModuleLabel"); + fPTBModuleLabel = p.get("PTBModuleLabel"); + fTDCModuleLabel = p.get("TDCModuleLabel"); + fTimingReferenceModuleLabel = p.get("TimingReferenceModuleLabel"); + fTPCSliceModuleLabel = p.get("TPCSliceModuleLabel"); + fCorrectedOpFlashModuleLabel = p.get("CorrectedOpFlashModuleLabel"); + fTPCTrackModuleLabel = p.get("TPCTrackModuleLabel"); + fCRTSpacePointMatchingModuleLabel = p.get("CRTSpacePointMatchingModuleLabel"); + fAllowedPTBHLTs = p.get>("AllowedPTBHLTs"); + + art::ServiceHandle fs; + + fSPTree = fs->make("spacepoints",""); + fSPTree->Branch("run", "int", &_run); + fSPTree->Branch("subrun", "int", &_subrun); + fSPTree->Branch("event", "int", &_event); + fSPTree->Branch("crt_timing_reference_type", "int", &_crt_timing_reference_type); + fSPTree->Branch("crt_timing_reference_channel", "int", &_crt_timing_reference_channel); + + fSPTree->Branch("etrig_good", "bool", &_etrig_good); + fSPTree->Branch("rwm_good", "bool", &_rwm_good); + fSPTree->Branch("ptb_hlt_beam_gate_good", "bool", &_ptb_hlt_beam_gate_good); + fSPTree->Branch("crt_t1_reset_good", "bool", &_crt_t1_reset_good); + fSPTree->Branch("rwm_etrig_diff", "double", &_rwm_etrig_diff); + fSPTree->Branch("ptb_hlt_beam_gate_etrig_diff", "double", &_ptb_hlt_beam_gate_etrig_diff); + fSPTree->Branch("rwm_crt_t1_reset_diff", "double", &_rwm_crt_t1_reset_diff); + fSPTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", "double", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fSPTree->Branch("rwm_ptb_hlt_beam_gate_diff", "double", &_rwm_ptb_hlt_beam_gate_diff); + + fSPTree->Branch("sp_nhits", "uint16_t", &_sp_nhits); + fSPTree->Branch("sp_tagger", "int16_t", &_sp_tagger); + fSPTree->Branch("sp_x", "double", &_sp_x); + fSPTree->Branch("sp_y", "double", &_sp_y); + fSPTree->Branch("sp_z", "double", &_sp_z); + fSPTree->Branch("sp_pe", "double", &_sp_pe); + fSPTree->Branch("sp_ts0", "double", &_sp_ts0); + fSPTree->Branch("sp_ts0_rwm_ref", "double", &_sp_ts0_rwm_ref); + fSPTree->Branch("sp_ts0_ptb_hlt_beam_gate_ref", "double", &_sp_ts0_ptb_hlt_beam_gate_ref); + fSPTree->Branch("sp_dts0", "double", &_sp_dts0); + fSPTree->Branch("sp_ts1", "double", &_sp_ts1); + fSPTree->Branch("sp_ts1_rwm_ref", "double", &_sp_ts1_rwm_ref); + fSPTree->Branch("sp_ts1_ptb_hlt_beam_gate_ref", "double", &_sp_ts1_ptb_hlt_beam_gate_ref); + fSPTree->Branch("sp_dts1", "double", &_sp_dts1); + fSPTree->Branch("sp_single_timing_chain", "bool", &_sp_single_timing_chain); + fSPTree->Branch("sp_timing_chain", "int16_t", &_sp_timing_chain); + fSPTree->Branch("sp_sh_channel_set", "std::vector", &_sp_sh_channel_set); + fSPTree->Branch("sp_sh_mac5_set", "std::vector", &_sp_sh_mac5_set); + fSPTree->Branch("sp_sh_timing_chain_set", "std::vector", &_sp_sh_timing_chain_set); + fSPTree->Branch("sp_sh_ts0_set", "std::vector", &_sp_sh_ts0_set); + fSPTree->Branch("sp_sh_ts1_set", "std::vector", &_sp_sh_ts1_set); + fSPTree->Branch("sp_sh_time_walk_set", "std::vector", &_sp_sh_time_walk_set); + fSPTree->Branch("sp_sh_prop_delay_set", "std::vector", &_sp_sh_prop_delay_set); + fSPTree->Branch("sp_sh_cable_length_set", "std::vector", &_sp_sh_cable_length_set); + fSPTree->Branch("sp_sh_calib_offset_ts0_set", "std::vector", &_sp_sh_calib_offset_ts0_set); + fSPTree->Branch("sp_sh_calib_offset_ts1_set", "std::vector", &_sp_sh_calib_offset_ts1_set); + + fTrTree = fs->make("tracks",""); + fTrTree->Branch("run", "int", &_run); + fTrTree->Branch("subrun", "int", &_subrun); + fTrTree->Branch("event", "int", &_event); + fTrTree->Branch("crt_timing_reference_type", "int", &_crt_timing_reference_type); + fTrTree->Branch("crt_timing_reference_channel", "int", &_crt_timing_reference_channel); + + fTrTree->Branch("etrig_good", "bool", &_etrig_good); + fTrTree->Branch("rwm_good", "bool", &_rwm_good); + fTrTree->Branch("ptb_hlt_beam_gate_good", "bool", &_ptb_hlt_beam_gate_good); + fTrTree->Branch("crt_t1_reset_good", "bool", &_crt_t1_reset_good); + fTrTree->Branch("rwm_etrig_diff", "double", &_rwm_etrig_diff); + fTrTree->Branch("ptb_hlt_beam_gate_etrig_diff", "double", &_ptb_hlt_beam_gate_etrig_diff); + fTrTree->Branch("rwm_crt_t1_reset_diff", "double", &_rwm_crt_t1_reset_diff); + fTrTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", "double", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fTrTree->Branch("rwm_ptb_hlt_beam_gate_diff", "double", &_rwm_ptb_hlt_beam_gate_diff); + + fTrTree->Branch("tr_start_x", "double", &_tr_start_x); + fTrTree->Branch("tr_start_y", "double", &_tr_start_y); + fTrTree->Branch("tr_start_z", "double", &_tr_start_z); + fTrTree->Branch("tr_end_x", "double", &_tr_end_x); + fTrTree->Branch("tr_end_y", "double", &_tr_end_y); + fTrTree->Branch("tr_end_z", "double", &_tr_end_z); + fTrTree->Branch("tr_dir_x", "double", &_tr_dir_x); + fTrTree->Branch("tr_dir_y", "double", &_tr_dir_y); + fTrTree->Branch("tr_dir_z", "double", &_tr_dir_z); + fTrTree->Branch("tr_ts0", "double", &_tr_ts0); + fTrTree->Branch("tr_ts0_rwm_ref", "double", &_tr_ts0_rwm_ref); + fTrTree->Branch("tr_ts0_ptb_hlt_beam_gate_ref", "double", &_tr_ts0_ptb_hlt_beam_gate_ref); + fTrTree->Branch("tr_ts1", "double", &_tr_ts1); + fTrTree->Branch("tr_ts1_rwm_ref", "double", &_tr_ts1_rwm_ref); + fTrTree->Branch("tr_ts1_ptb_hlt_beam_gate_ref", "double", &_tr_ts1_ptb_hlt_beam_gate_ref); + fTrTree->Branch("tr_pe", "double", &_tr_pe); + fTrTree->Branch("tr_length", "double", &_tr_length); + fTrTree->Branch("tr_length_tof", "double", &_tr_length_tof); + fTrTree->Branch("tr_tof_ts0", "double", &_tr_tof_ts0); + fTrTree->Branch("tr_tof_diff_ts0", "double", &_tr_tof_diff_ts0); + fTrTree->Branch("tr_tof_ts1", "double", &_tr_tof_ts1); + fTrTree->Branch("tr_tof_diff_ts1", "double", &_tr_tof_diff_ts1); + fTrTree->Branch("tr_theta", "double", &_tr_theta); + fTrTree->Branch("tr_phi", "double", &_tr_phi); + fTrTree->Branch("tr_triple", "bool", &_tr_triple); + fTrTree->Branch("tr_tagger1", "int16_t", &_tr_tagger1); + fTrTree->Branch("tr_tagger2", "int16_t", &_tr_tagger2); + fTrTree->Branch("tr_tagger3", "int16_t", &_tr_tagger3); + fTrTree->Branch("tr_start_tagger", "int16_t", &_tr_start_tagger); + fTrTree->Branch("tr_start_dts0", "double", &_tr_start_dts0); + fTrTree->Branch("tr_start_single_timing_chain", "bool", &_tr_start_single_timing_chain); + fTrTree->Branch("tr_start_timing_chain", "int16_t", &_tr_start_timing_chain); + fTrTree->Branch("tr_end_tagger", "int16_t", &_tr_end_tagger); + fTrTree->Branch("tr_end_dts0", "double", &_tr_end_dts0); + fTrTree->Branch("tr_end_single_timing_chain", "bool", &_tr_end_single_timing_chain); + fTrTree->Branch("tr_end_timing_chain", "int16_t", &_tr_end_timing_chain); + + fTPCTree = fs->make("slices",""); + fTPCTree->Branch("run", "int", &_run); + fTPCTree->Branch("subrun", "int", &_subrun); + fTPCTree->Branch("event", "int", &_event); + fTPCTree->Branch("crt_timing_reference_type", "int", &_crt_timing_reference_type); + fTPCTree->Branch("crt_timing_reference_channel", "int", &_crt_timing_reference_channel); + + fTPCTree->Branch("etrig_good", "bool", &_etrig_good); + fTPCTree->Branch("rwm_good", "bool", &_rwm_good); + fTPCTree->Branch("ptb_hlt_beam_gate_good", "bool", &_ptb_hlt_beam_gate_good); + fTPCTree->Branch("crt_t1_reset_good", "bool", &_crt_t1_reset_good); + fTPCTree->Branch("rwm_etrig_diff", "double", &_rwm_etrig_diff); + fTPCTree->Branch("ptb_hlt_beam_gate_etrig_diff", "double", &_ptb_hlt_beam_gate_etrig_diff); + fTPCTree->Branch("rwm_crt_t1_reset_diff", "double", &_rwm_crt_t1_reset_diff); + fTPCTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", "double", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fTPCTree->Branch("rwm_ptb_hlt_beam_gate_diff", "double", &_rwm_ptb_hlt_beam_gate_diff); + + fTPCTree->Branch("tpc_has_corrected_opflash", "bool", &_tpc_has_corrected_opflash); + fTPCTree->Branch("tpc_has_crt_sp_match", "bool", &_tpc_has_crt_sp_match); + fTPCTree->Branch("tpc_opflash_t0", "double", &_tpc_opflash_t0); + fTPCTree->Branch("tpc_opflash_nutof_light", "double", &_tpc_opflash_nutof_light); + fTPCTree->Branch("tpc_opflash_nutof_charge", "double", &_tpc_opflash_nutof_charge); + fTPCTree->Branch("tpc_opflash_t0_corrected", "double", &_tpc_opflash_t0_corrected); + fTPCTree->Branch("tpc_opflash_t0_corrected_rwm", "double", &_tpc_opflash_t0_corrected_rwm); + fTPCTree->Branch("tpc_crt_sp_score", "double", &_tpc_crt_sp_score); + fTPCTree->Branch("tpc_crt_sp_ts0", "double", &_tpc_crt_sp_ts0); + fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref", "double", &_tpc_crt_sp_ts0_rwm_ref); + fTPCTree->Branch("tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref", "double", &_tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref); + fTPCTree->Branch("tpc_crt_sp_dts0", "double", &_tpc_crt_sp_dts0); + fTPCTree->Branch("tpc_crt_sp_ts1", "double", &_tpc_crt_sp_ts1); + fTPCTree->Branch("tpc_crt_sp_ts1_rwm_ref", "double", &_tpc_crt_sp_ts1_rwm_ref); + fTPCTree->Branch("tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref", "double", &_tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref); + fTPCTree->Branch("tpc_crt_sp_dts1", "double", &_tpc_crt_sp_dts1); +} + +void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) +{ + _run = e.id().run(); + _subrun = e.id().subRun(); + _event = e.id().event(); + + _crt_timing_reference_type = -1; + _crt_timing_reference_channel = -1; + + art::Handle TimingReferenceHandle; + e.getByLabel(fTimingReferenceModuleLabel, TimingReferenceHandle); + if(TimingReferenceHandle.isValid()) + { + _crt_timing_reference_type = TimingReferenceHandle->timingType; + _crt_timing_reference_channel = TimingReferenceHandle->timingChannel; + } + + // Get PTBs + art::Handle> PTBHandle; + e.getByLabel(fPTBModuleLabel, PTBHandle); + if(!PTBHandle.isValid()){ + std::cout << "PTB product " << fPTBModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> PTBVec; + art::fill_ptr_vector(PTBVec, PTBHandle); + + // Fill PTB variables + AnalysePTBs(PTBVec); + + // Get TDCs + art::Handle> TDCHandle; + e.getByLabel(fTDCModuleLabel, TDCHandle); + if(!TDCHandle.isValid()){ + std::cout << "TDC product " << fTDCModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> TDCVec; + art::fill_ptr_vector(TDCVec, TDCHandle); + + // Fill TDC variables + AnalyseTDCs(TDCVec); + + SortReferencing(); + + // Get CRTSpacePoints + art::Handle> CRTSpacePointHandle; + e.getByLabel(fCRTSpacePointModuleLabel, CRTSpacePointHandle); + if(!CRTSpacePointHandle.isValid()){ + std::cout << "CRTSpacePoint product " << fCRTSpacePointModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTSpacePointVec; + art::fill_ptr_vector(CRTSpacePointVec, CRTSpacePointHandle); + + // Get CRTSpacePoint to CRTCluster Assns + art::FindOneP spacepointsToClusters(CRTSpacePointHandle, e, fCRTSpacePointModuleLabel); + + // Get CRTClusters + art::Handle> CRTClusterHandle; + e.getByLabel(fCRTClusterModuleLabel, CRTClusterHandle); + if(!CRTClusterHandle.isValid()){ + std::cout << "CRTCluster product " << fCRTClusterModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + // Get CRTCluster to CRTStripHit Assns + art::FindManyP clustersToStripHits(CRTClusterHandle, e, fCRTClusterModuleLabel); + + // Fill CRTSpacePoint variables + AnalyseCRTSpacePoints(CRTSpacePointVec, spacepointsToClusters, clustersToStripHits); + + // Get CRTTracks + art::Handle> CRTTrackHandle; + e.getByLabel(fCRTTrackModuleLabel, CRTTrackHandle); + if(!CRTTrackHandle.isValid()){ + std::cout << "CRTTrack product " << fCRTTrackModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> CRTTrackVec; + art::fill_ptr_vector(CRTTrackVec, CRTTrackHandle); + + // Get CRTTrack to CRTSpacePoint Assns + art::FindManyP tracksToSpacePoints(CRTTrackHandle, e, fCRTTrackModuleLabel); + + // Fill CRTTrack variables + AnalyseCRTTracks(CRTTrackVec, tracksToSpacePoints, spacepointsToClusters, clustersToStripHits); + + // Get TPCSlices + art::Handle> TPCSliceHandle; + e.getByLabel(fTPCSliceModuleLabel, TPCSliceHandle); + if(!TPCSliceHandle.isValid()){ + std::cout << "TPCSlice product " << fTPCSliceModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + std::vector> TPCSliceVec; + art::fill_ptr_vector(TPCSliceVec, TPCSliceHandle); + + // Get TPCSlice to CorrectedOpFlash Assns + art::FindManyP sliceToCorrectedOpFlashes(TPCSliceHandle, e, fCorrectedOpFlashModuleLabel); + + // Get TPCSlice to PFP Assns + art::FindManyP sliceToPFPs(TPCSliceHandle, e, fTPCSliceModuleLabel); + + // Get TPCPFPs + art::Handle> TPCPFPHandle; + e.getByLabel(fTPCSliceModuleLabel, TPCPFPHandle); + if(!TPCPFPHandle.isValid()){ + std::cout << "TPCPFP product " << fTPCSliceModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + // Get PFP to Track Assns + art::FindOneP pfpToTrack(TPCPFPHandle, e, fTPCTrackModuleLabel); + + // Get TPCTracks + art::Handle> TPCTrackHandle; + e.getByLabel(fTPCTrackModuleLabel, TPCTrackHandle); + if(!TPCTrackHandle.isValid()){ + std::cout << "TPCTrack product " << fTPCTrackModuleLabel << " not found..." << std::endl; + throw std::exception(); + } + + // Get Track to CRTSpacePoint Assns + art::FindOneP trackToCRTSpacePoint(TPCTrackHandle, e, fCRTSpacePointMatchingModuleLabel); + + AnalyseTPCSlices(TPCSliceVec, sliceToCorrectedOpFlashes, sliceToPFPs, pfpToTrack, trackToCRTSpacePoint, spacepointsToClusters, clustersToStripHits); +} + +void sbnd::crt::CRTTimingAnalysis::AnalysePTBs(std::vector> &PTBVec) +{ + unsigned nHLTs = 0; + + for(auto const& ptb : PTBVec) + nHLTs += ptb->GetNHLTriggers(); + + _ptb_hlt_trigger.resize(nHLTs); + _ptb_hlt_timestamp.resize(nHLTs); + + unsigned hlt_i = 0; + + for(auto const& ptb : PTBVec) + { + for(unsigned i = 0; i < ptb->GetNHLTriggers(); ++i) + { + _ptb_hlt_trigger[hlt_i] = ptb->GetHLTrigger(i).trigger_word; + _ptb_hlt_timestamp[hlt_i] = ptb->GetHLTrigger(i).timestamp * 20; + + ++hlt_i; + } + } + + unsigned nLLTs = 0; + + for(auto const& ptb : PTBVec) + nLLTs += ptb->GetNLLTriggers(); + + _ptb_llt_trigger.resize(nLLTs); + _ptb_llt_timestamp.resize(nLLTs); + + unsigned llt_i = 0; + + for(auto const& ptb : PTBVec) + { + for(unsigned i = 0; i < ptb->GetNLLTriggers(); ++i) + { + _ptb_llt_trigger[llt_i] = ptb->GetLLTrigger(i).trigger_word; + _ptb_llt_timestamp[llt_i] = ptb->GetLLTrigger(i).timestamp * 20; + + ++llt_i; + } + } +} + +void sbnd::crt::CRTTimingAnalysis::AnalyseTDCs(std::vector> &TDCVec) +{ + const unsigned nTDCs = TDCVec.size(); + + _tdc_channel.resize(nTDCs); + _tdc_timestamp.resize(nTDCs); + _tdc_offset.resize(nTDCs); + _tdc_name.resize(nTDCs); + + unsigned tdc_i = 0; + + for(auto const& tdc : TDCVec) + { + _tdc_channel[tdc_i] = tdc->Channel(); + _tdc_timestamp[tdc_i] = tdc->Timestamp(); + _tdc_offset[tdc_i] = tdc->Offset(); + _tdc_name[tdc_i] = tdc->Name(); + + ++tdc_i; + } +} + +void sbnd::crt::CRTTimingAnalysis::SortReferencing() +{ + _etrig_good = false; _rwm_good = false; _ptb_hlt_beam_gate_good = false; _crt_t1_reset_good = false; + _rwm_etrig_diff = std::numeric_limits::max(); _ptb_hlt_beam_gate_etrig_diff = std::numeric_limits::max(); + _rwm_crt_t1_reset_diff = std::numeric_limits::max(); _ptb_hlt_beam_gate_crt_t1_reset_diff = std::numeric_limits::max(); + _rwm_ptb_hlt_beam_gate_diff = std::numeric_limits::max(); + + int etrig_count = 0, etrig_id = -1, rwm_count = 0, rwm_id = -1, crt_t1_reset_count = 0, crt_t1_reset_id = -1; + + for(unsigned int tdc_i = 0; tdc_i < _tdc_channel.size(); ++tdc_i) + { + if(_tdc_channel[tdc_i] == 4) + { + ++etrig_count; + etrig_id = tdc_i; + } + else if(_tdc_channel[tdc_i] == 2) + { + ++rwm_count; + rwm_id = tdc_i; + } + else if(_tdc_channel[tdc_i] == 0) + { + ++crt_t1_reset_count; + crt_t1_reset_id = tdc_i; + } + } + + uint64_t etrig = std::numeric_limits::max(), rwm = std::numeric_limits::max(), + hlt = std::numeric_limits::max(), crt_t1_reset = std::numeric_limits::max(); + + if(etrig_count == 1) + { + _etrig_good = true; + etrig = _tdc_timestamp[etrig_id]; + } + + if(rwm_count == 1) + { + _rwm_good = true; + rwm = _tdc_timestamp[rwm_id]; + } + + if(etrig_count == 1) + { + double closest_diff = std::numeric_limits::max(); + + for(unsigned int ptb_i = 0; ptb_i < _ptb_hlt_trigger.size(); ++ptb_i) + { + std::bitset<32> hlt_bitmask = std::bitset<32>(_ptb_hlt_trigger[ptb_i]); + + for(uint32_t allowed_hlt : fAllowedPTBHLTs) + { + if(hlt_bitmask[allowed_hlt]) + { + _ptb_hlt_beam_gate_good = true; + + uint64_t temp_hlt = _ptb_hlt_timestamp[ptb_i]; + double diff = etrig > temp_hlt ? etrig - temp_hlt : -1. * (temp_hlt - etrig); + + if(std::abs(diff) < closest_diff) + { + closest_diff = diff; + hlt = temp_hlt; + } + } + } + } + } + + if(crt_t1_reset_count == 1) + { + _crt_t1_reset_good = true; + crt_t1_reset = _tdc_timestamp[crt_t1_reset_id]; + } + + if(_etrig_good && _rwm_good) + _rwm_etrig_diff = etrig > rwm ? etrig - rwm : -1. * (rwm - etrig); + + if(_etrig_good && _ptb_hlt_beam_gate_good) + _ptb_hlt_beam_gate_etrig_diff = etrig > hlt ? etrig - hlt : -1. * (hlt - etrig); + + if(_crt_t1_reset_good && _rwm_good) + _rwm_crt_t1_reset_diff = crt_t1_reset > rwm ? crt_t1_reset - rwm : -1. * (rwm - crt_t1_reset); + + if(_etrig_good && _crt_t1_reset_good && _ptb_hlt_beam_gate_good) + _ptb_hlt_beam_gate_crt_t1_reset_diff = crt_t1_reset > hlt ? crt_t1_reset - hlt : -1. * (hlt - crt_t1_reset); + + if(_etrig_good && _rwm_good && _ptb_hlt_beam_gate_good) + _rwm_ptb_hlt_beam_gate_diff = hlt > rwm ? hlt - rwm : -1. * (rwm - hlt); +} + +void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vector> &CRTSpacePointVec, + const art::FindOneP &spacepointsToClusters, + const art::FindManyP &clustersToStripHits) +{ +} + +void sbnd::crt::CRTTimingAnalysis::AnalyseCRTTracks(const std::vector> &CRTTrackVec, + const art::FindManyP &tracksToSpacePoints, + const art::FindOneP &spacepointsToClusters, + const art::FindManyP &clustersToStripHits) +{ +} + +void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vector> &TPCSliceVec, + const art::FindManyP &sliceToCorrectedOpFlashes, + const art::FindManyP &sliceToPFPs, + const art::FindOneP &pfpToTrack, + const art::FindOneP &trackToCRTSpacePoint, + const art::FindOneP &spacepointsToClusters, + const art::FindManyP &clustersToStripHits) +{ +} + +DEFINE_ART_MODULE(sbnd::crt::CRTTimingAnalysis) diff --git a/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl b/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl new file mode 100644 index 000000000..4a9bff36a --- /dev/null +++ b/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl @@ -0,0 +1,19 @@ +BEGIN_PROLOG + +crttophatana_data_sbnd: +{ + module_type: "CRTTimingAnalysis" + CRTClusterModuleLabel: "crtclustering" + CRTSpacePointModuleLabel: "crtspacepoints" + CRTTrackModuleLabel: "crttracks" + PTBModuleLabel: "ptbdecoder" + TDCModuleLabel: "tdcdecoder" + TimingReferenceModuleLabel: "crtstrips" + TPCSliceModuleLabel: "pandoraSCE" + CorrectedOpFlashModuleLabel: "lightpropagationcorrectionSCE" + TPCTrackModuleLabel: "pandoraSCETrack" + CRTSpacePointMatchingModuleLabel: "crtspacepointmatchingSCE" + AllowedPTBHLTs: [ 26, 27 ] +} + +END_PROLOG From 46bb0a2a5136161c4d4e7577713fef732d0d195b Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 24 Feb 2026 11:04:27 -0600 Subject: [PATCH 52/75] Refactor cluster characterisation to allow external use of timing corrections --- .../CRTReco/CRTClusterCharacterisationAlg.cc | 31 ++++++++++++------- .../CRTReco/CRTClusterCharacterisationAlg.h | 6 +++- 2 files changed, 24 insertions(+), 13 deletions(-) diff --git a/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.cc b/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.cc index 1b7e296cd..49c6dbb4c 100644 --- a/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.cc +++ b/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.cc @@ -198,14 +198,8 @@ namespace sbnd::crt { void CRTClusterCharacterisationAlg::CorrectTime(const art::Ptr &hit0, const art::Ptr &hit1, const geo::Point_t &pos, double &t0, double &et0, double &t1, double &et1) { - const double dist0 = fCRTGeoService->DistanceDownStrip(pos, hit0->Channel()); - const double dist1 = fCRTGeoService->DistanceDownStrip(pos, hit1->Channel()); - - const double pe0 = ReconstructPE(hit0, dist0); - const double pe1 = ReconstructPE(hit1, dist1); - - const double corr0 = TimingCorrectionOffset(dist0, pe0); - const double corr1 = TimingCorrectionOffset(dist1, pe1); + const double corr0 = TimingCorrectionOffset(hit0, pos); + const double corr1 = TimingCorrectionOffset(hit1, pos); t0 = (hit0->Ts0() - corr0 + hit1->Ts0() - corr1) / 2.; et0 = std::abs((hit0->Ts0() - corr0) - (hit1->Ts0() - corr1)) / 2.; @@ -214,14 +208,27 @@ namespace sbnd::crt { et1 = std::abs((hit0->Ts1() - corr0) - (hit1->Ts1() - corr1)) / 2.; } - double CRTClusterCharacterisationAlg::TimingCorrectionOffset(const double &dist, const double &pe) + double CRTClusterCharacterisationAlg::TimingCorrectionOffset(const art::Ptr &hit, const geo::Point_t &pos) { - - double t_TimeWalk = fTimeWalkNorm * std::exp(- fTimeWalkScale * pe); - double t_PropDelay = fPropDelay * dist; + double t_TimeWalk = TimeWalk(hit, pos); + double t_PropDelay = PropagationDelay(hit, pos); return t_PropDelay + t_TimeWalk; } + double CRTClusterCharacterisationAlg::TimeWalk(const art::Ptr &hit, const geo::Point_t &pos) + { + const double dist = fCRTGeoService->DistanceDownStrip(pos, hit->Channel()); + const double pe = ReconstructPE(hit, dist); + + return fTimeWalkNorm * std::exp(-fTimeWalkScale * pe); + } + + double CRTClusterCharacterisationAlg::PropagationDelay(const art::Ptr &hit, const geo::Point_t &pos) + { + const double dist = fCRTGeoService->DistanceDownStrip(pos, hit->Channel()); + return fPropDelay * dist; + } + void CRTClusterCharacterisationAlg::AggregatePositions(const std::vector &complete_spacepoints, geo::Point_t &pos, geo::Point_t &err) { double sum_x = 0., sum_y = 0., sum_z = 0.; diff --git a/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h b/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h index a622ef28d..373d47ed7 100644 --- a/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h +++ b/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h @@ -65,7 +65,11 @@ namespace sbnd::crt { void CorrectTime(const art::Ptr &hit0, const art::Ptr &hit1, const geo::Point_t &pos, double &t0, double &et0, double &t1, double &et1); - double TimingCorrectionOffset(const double &dist, const double &pe); + double TimingCorrectionOffset(const art::Ptr &hit, const geo::Point_t &pos); + + double TimeWalk(const art::Ptr &hit, const geo::Point_t &pos); + + double PropagationDelay(const art::Ptr &hit, const geo::Point_t &pos); void AggregatePositions(const std::vector &complete_spacepoints, geo::Point_t &pos, geo::Point_t &err); From 1459913bec4e7d241082900cad1ffa980ed0ca90 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 24 Feb 2026 11:10:31 -0600 Subject: [PATCH 53/75] Update channel map service to add timing chains --- .../ChannelMaps/CRT/CRTChannelMapService.h | 12 ++++ .../CRT/CRTChannelMapService_service.cc | 64 ++++++++++++++++--- .../CRT/SBNDCRTTimingChainMap_v1.txt | 20 ++++++ .../CRT/crt_channel_map_service_sbnd.fcl | 3 +- 4 files changed, 90 insertions(+), 9 deletions(-) create mode 100644 sbndcode/ChannelMaps/CRT/SBNDCRTTimingChainMap_v1.txt diff --git a/sbndcode/ChannelMaps/CRT/CRTChannelMapService.h b/sbndcode/ChannelMaps/CRT/CRTChannelMapService.h index fc22880d1..6fce72894 100644 --- a/sbndcode/ChannelMaps/CRT/CRTChannelMapService.h +++ b/sbndcode/ChannelMaps/CRT/CRTChannelMapService.h @@ -59,6 +59,12 @@ class SBND::CRTChannelMapService { unsigned int GetMAC5FromOfflineChannelID(const unsigned int offline_channel_id); + unsigned int GetTimingChainFromOfflineModuleID(unsigned int offline_module_id); + + unsigned int GetTimingChainFromOfflineChannelID(unsigned int offline_channel_id); + + unsigned int GetTimingChainFromMAC5(unsigned int mac5); + private: typedef struct ModuleInfo { @@ -75,6 +81,12 @@ class SBND::CRTChannelMapService { // look up channel info by MAC5 std::unordered_map fModuleInfoFromMAC5; ModuleInfo_t GetModuleInfoFromMAC5(unsigned int mac5) const; + + // look up timing chain by offline module number + std::unordered_map fTimingChainFromOfflineID; + + // look up channel info by MAC5 + std::unordered_map fTimingChainFromMAC5; }; DECLARE_ART_SERVICE(SBND::CRTChannelMapService, LEGACY) diff --git a/sbndcode/ChannelMaps/CRT/CRTChannelMapService_service.cc b/sbndcode/ChannelMaps/CRT/CRTChannelMapService_service.cc index 3e3d45cfa..63f27ad88 100644 --- a/sbndcode/ChannelMaps/CRT/CRTChannelMapService_service.cc +++ b/sbndcode/ChannelMaps/CRT/CRTChannelMapService_service.cc @@ -17,28 +17,30 @@ SBND::CRTChannelMapService::CRTChannelMapService(fhicl::ParameterSet const& pset) { - const std::string channelMapFile = pset.get("FileName"); + const std::string channelMapFile = pset.get("ChannelMapFileName"); + const std::string timingChainMapFile = pset.get("TimingChainMapFileName"); - std::string fullname; + std::string channelMapFileFullName, timingChainMapFileFullName; cet::search_path sp("FW_SEARCH_PATH"); - sp.find_file(channelMapFile, fullname); + sp.find_file(channelMapFile, channelMapFileFullName); + sp.find_file(timingChainMapFile, timingChainMapFileFullName); - if(fullname.empty()) + if(channelMapFileFullName.empty()) { std::cout << "SBND::CRTChannelMapService Input file " << channelMapFile << " not found" << std::endl; throw cet::exception("File not found"); } std::cout << "SBND CRT Channel Map: Building map from file " << channelMapFile << std::endl; - std::ifstream inFile(fullname, std::ios::in); + std::ifstream channelMapInFile(channelMapFileFullName, std::ios::in); std::string line; - while(std::getline(inFile,line)) + while(std::getline(channelMapInFile, line)) { std::stringstream linestream(line); SBND::CRTChannelMapService::ModuleInfo_t m; - linestream + linestream >> m.offline_module_id >> m.mac5 >> m.channel_order_swapped; @@ -49,7 +51,38 @@ SBND::CRTChannelMapService::CRTChannelMapService(fhicl::ParameterSet const& pset fModuleInfoFromMAC5[m.mac5] = m; } - inFile.close(); + channelMapInFile.close(); + + if(timingChainMapFileFullName.empty()) + { + std::cout << "SBND::CRTChannelMapService Input file " << timingChainMapFile << " not found" << std::endl; + throw cet::exception("File not found"); + } + + std::cout << "SBND CRT Channel Map: Building timing chain map from file " << timingChainMapFile << std::endl; + std::ifstream timingChainMapInFile(timingChainMapFileFullName, std::ios::in); + + while(std::getline(timingChainMapInFile, line)) + { + std::stringstream linestream(line); + + unsigned int timing_chain = std::numeric_limits::max(); + unsigned int n = 0; + + linestream + >> timing_chain + >> n; + + for(unsigned int i = 0; i < n; ++i) + { + unsigned int offline_module_id = std::numeric_limits::max(); + linestream >> offline_module_id; + fTimingChainFromOfflineID[offline_module_id] = timing_chain; + fTimingChainFromMAC5[GetMAC5FromOfflineModuleID(offline_module_id)] = timing_chain; + } + } + + timingChainMapInFile.close(); } SBND::CRTChannelMapService::ModuleInfo_t SBND::CRTChannelMapService::GetModuleInfoFromMAC5(unsigned int mac5) const @@ -202,4 +235,19 @@ unsigned int SBND::CRTChannelMapService::GetMAC5FromOfflineChannelID(const unsig return GetMAC5FromOfflineModuleID(GetOfflineModuleIDFromOfflineChannelID(offline_channel_id)); } +unsigned int SBND::CRTChannelMapService::GetTimingChainFromOfflineModuleID(unsigned int offline_module_id) +{ + return fTimingChainFromOfflineID[offline_module_id]; +} + +unsigned int SBND::CRTChannelMapService::GetTimingChainFromOfflineChannelID(unsigned int offline_channel_id) +{ + return GetTimingChainFromOfflineModuleID(GetOfflineModuleIDFromOfflineChannelID(offline_channel_id)); +} + +unsigned int SBND::CRTChannelMapService::GetTimingChainFromMAC5(unsigned int mac5) +{ + return fTimingChainFromMAC5[mac5]; +} + DEFINE_ART_SERVICE(SBND::CRTChannelMapService) diff --git a/sbndcode/ChannelMaps/CRT/SBNDCRTTimingChainMap_v1.txt b/sbndcode/ChannelMaps/CRT/SBNDCRTTimingChainMap_v1.txt new file mode 100644 index 000000000..e37aa53cb --- /dev/null +++ b/sbndcode/ChannelMaps/CRT/SBNDCRTTimingChainMap_v1.txt @@ -0,0 +1,20 @@ +0 8 127 126 125 124 123 122 120 121 +1 6 139 128 137 138 136 135 +2 6 134 133 132 131 130 129 +3 8 63 62 54 55 56 57 58 59 +4 8 64 65 50 51 52 53 61 60 +5 6 81 80 82 79 83 78 +6 6 66 67 68 69 77 76 +7 6 70 71 72 73 74 75 +8 9 115 106 107 108 109 110 111 112 113 +9 9 116 117 118 119 102 103 104 105 114 +10 9 101 84 85 86 87 96 95 94 93 +11 9 100 99 98 97 88 89 90 91 92 +12 6 33 32 31 30 40 41 +13 6 42 43 44 25 26 27 +14 7 37 38 39 29 28 49 48 +15 6 36 35 34 45 46 47 +16 6 21 22 23 24 9 8 +17 6 7 6 5 19 18 17 +18 7 12 11 10 15 16 0 1 +19 6 13 14 20 4 3 2 diff --git a/sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl b/sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl index a34f136cd..35945a2b4 100644 --- a/sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl +++ b/sbndcode/ChannelMaps/CRT/crt_channel_map_service_sbnd.fcl @@ -2,7 +2,8 @@ BEGIN_PROLOG crt_channel_map_sbnd: { - FileName: "SBNDCRTChannelMap_Commissioning_v5.txt" + ChannelMapFileName: "SBNDCRTChannelMap_Commissioning_v5.txt" + TimingChainMapFileName: "SBNDCRTTimingChainMap_v1.txt" } END_PROLOG From 75870c2a5fb1d21a5e805874bb8382eb55d9f49e Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 24 Feb 2026 11:12:19 -0600 Subject: [PATCH 54/75] Fill space point branches in timing analysis --- sbndcode/CRT/CRTAna/CMakeLists.txt | 2 + .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 154 +++++++++++++++++- 2 files changed, 153 insertions(+), 3 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CMakeLists.txt b/sbndcode/CRT/CRTAna/CMakeLists.txt index 05de4d016..ad4284386 100644 --- a/sbndcode/CRT/CRTAna/CMakeLists.txt +++ b/sbndcode/CRT/CRTAna/CMakeLists.txt @@ -10,6 +10,8 @@ art_make( sbnobj::SBND_Timing sbnobj::Common_Reco sbndcode_CRT_CRTBackTracker + sbndcode_CRT_CRTReco + sbndcode_ChannelMaps_CRT_CRTChannelMapService_service ) install_fhicl() diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index 3fa9d0fd6..8b23a9699 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -35,6 +35,8 @@ #include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" #include "sbndcode/Decoders/PTB/sbndptb.h" #include "sbndcode/Timing/SBNDRawTimingObj.h" +#include "sbndcode/Calibration/CRTDatabaseInterface/CRTCalibrationDatabase.h" +#include "sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h" namespace sbnd::crt { class CRTTimingAnalysis; @@ -65,6 +67,15 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { const art::FindOneP &spacepointsToClusters, const art::FindManyP &clustersToStripHits); + void ResetSPVariables(); + + void ResizeSPSHVecs(const unsigned n); + + double IntrinsicResolution(const std::vector &_sp_sh_channel_set, + const std::vector &_sp_sh_ts_set, + const std::vector &_sp_sh_time_walk_set, + const std::vector &_sp_sh_prop_delay_set); + void AnalyseCRTTracks(const std::vector> &CRTTrackVec, const art::FindManyP &tracksToSpacePoints, const art::FindOneP &spacepointsToClusters, @@ -80,7 +91,10 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { private: - art::ServiceHandle fCRTGeoService; + art::ServiceHandle fCRTGeoService; + art::ServiceHandle fCRTChannelMapService; + sbndDB::CRTCalibrationDatabase const *fCRTCalibrationDatabaseService; + CRTClusterCharacterisationAlg fCRTClusterCharacAlg; // fcl Controlled Variables std::string fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, fCRTTrackModuleLabel, @@ -143,8 +157,9 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { std::vector _sp_sh_ts1_set; std::vector _sp_sh_time_walk_set; std::vector _sp_sh_prop_delay_set; - std::vector _sp_sh_cable_length_set; + std::vector _sp_sh_cable_length_ts0_set; std::vector _sp_sh_calib_offset_ts0_set; + std::vector _sp_sh_cable_length_ts1_set; std::vector _sp_sh_calib_offset_ts1_set; double _tr_start_x; @@ -204,6 +219,7 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) : EDAnalyzer{p} + , fCRTClusterCharacAlg(p.get("CRTClusterCharacterisationAlg", fhicl::ParameterSet())) { fCRTClusterModuleLabel = p.get("CRTClusterModuleLabel"); fCRTSpacePointModuleLabel = p.get("CRTSpacePointModuleLabel"); @@ -259,8 +275,9 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fSPTree->Branch("sp_sh_ts1_set", "std::vector", &_sp_sh_ts1_set); fSPTree->Branch("sp_sh_time_walk_set", "std::vector", &_sp_sh_time_walk_set); fSPTree->Branch("sp_sh_prop_delay_set", "std::vector", &_sp_sh_prop_delay_set); - fSPTree->Branch("sp_sh_cable_length_set", "std::vector", &_sp_sh_cable_length_set); + fSPTree->Branch("sp_sh_cable_length_ts0_set", "std::vector", &_sp_sh_cable_length_ts0_set); fSPTree->Branch("sp_sh_calib_offset_ts0_set", "std::vector", &_sp_sh_calib_offset_ts0_set); + fSPTree->Branch("sp_sh_cable_length_ts1_set", "std::vector", &_sp_sh_cable_length_ts1_set); fSPTree->Branch("sp_sh_calib_offset_ts1_set", "std::vector", &_sp_sh_calib_offset_ts1_set); fTrTree = fs->make("tracks",""); @@ -644,6 +661,137 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vector &spacepointsToClusters, const art::FindManyP &clustersToStripHits) { + for(auto const& sp : CRTSpacePointVec) + { + ResetSPVariables(); + + const art::Ptr cl = spacepointsToClusters.at(sp.key()); + + const std::vector> shs = clustersToStripHits.at(cl.key()); + const unsigned n_shs = shs.size(); + ResizeSPSHVecs(n_shs); + + _sp_nhits = cl->NHits(); + _sp_tagger = cl->Tagger(); + _sp_x = sp->X(); + _sp_y = sp->Y(); + _sp_z = sp->Z(); + _sp_pe = sp->PE(); + _sp_ts0 = sp->Ts0(); + _sp_ts0_rwm_ref = _sp_ts0 + _rwm_etrig_diff; + _sp_ts0_ptb_hlt_beam_gate_ref = _sp_ts0 + _ptb_hlt_beam_gate_etrig_diff; + _sp_ts1 = sp->Ts1(); + _sp_ts1_rwm_ref = _sp_ts1 + _rwm_crt_t1_reset_diff; + _sp_ts1_ptb_hlt_beam_gate_ref = _sp_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; + + for(unsigned i = 0; i < n_shs; ++i) + { + const art::Ptr sh = shs[i]; + + _sp_sh_channel_set[i] = sh->Channel(); + _sp_sh_mac5_set[i] = fCRTChannelMapService->GetMAC5FromOfflineChannelID(_sp_sh_channel_set[i]); + _sp_sh_timing_chain_set[i] = fCRTChannelMapService->GetTimingChainFromOfflineChannelID(_sp_sh_channel_set[i]); + _sp_sh_ts0_set[i] = sh->Ts0(); + _sp_sh_ts1_set[i] = sh->Ts1(); + _sp_sh_time_walk_set[i] = fCRTClusterCharacAlg.TimeWalk(sh, {_sp_x, _sp_y, _sp_z}); + _sp_sh_prop_delay_set[i] = fCRTClusterCharacAlg.PropagationDelay(sh, {_sp_x, _sp_y, _sp_z}); + _sp_sh_cable_length_ts0_set[i] = fCRTCalibrationDatabaseService->getT0CableLengthOffset(_sp_sh_mac5_set[i]); + _sp_sh_calib_offset_ts0_set[i] = fCRTCalibrationDatabaseService->getT0CalibratedOffset(_sp_sh_mac5_set[i]); + _sp_sh_cable_length_ts1_set[i] = fCRTCalibrationDatabaseService->getT1CableLengthOffset(_sp_sh_mac5_set[i]); + _sp_sh_calib_offset_ts1_set[i] = fCRTCalibrationDatabaseService->getT1CalibratedOffset(_sp_sh_mac5_set[i]); + } + + _sp_dts0 = IntrinsicResolution(_sp_sh_channel_set, _sp_sh_ts0_set, _sp_sh_time_walk_set, _sp_sh_prop_delay_set); + _sp_dts1 = IntrinsicResolution(_sp_sh_channel_set, _sp_sh_ts1_set, _sp_sh_time_walk_set, _sp_sh_prop_delay_set); + + std::set timing_chain_set(_sp_sh_timing_chain_set.begin(), _sp_sh_timing_chain_set.end()); + _sp_single_timing_chain = timing_chain_set.size() == 1; + _sp_timing_chain = _sp_single_timing_chain ? *timing_chain_set.begin() : -1; + + fSPTree->Fill(); + } +} + +void sbnd::crt::CRTTimingAnalysis::ResetSPVariables() +{ + _sp_nhits = std::numeric_limits::max(); + + _sp_tagger = CRTTagger::kUndefinedTagger; + + _sp_x = std::numeric_limits::lowest(); + _sp_y = std::numeric_limits::lowest(); + _sp_z = std::numeric_limits::lowest(); + _sp_pe = std::numeric_limits::lowest(); + _sp_ts0 = std::numeric_limits::lowest(); + _sp_ts0_rwm_ref = std::numeric_limits::lowest(); + _sp_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _sp_dts0 = std::numeric_limits::lowest(); + _sp_ts1 = std::numeric_limits::lowest(); + _sp_ts1_rwm_ref = std::numeric_limits::lowest(); + _sp_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _sp_dts1 = std::numeric_limits::lowest(); + + _sp_single_timing_chain = false; + + _sp_timing_chain = std::numeric_limits::lowest(); + + _sp_sh_channel_set.clear(); + _sp_sh_mac5_set.clear(); + _sp_sh_timing_chain_set.clear(); + _sp_sh_ts0_set.clear(); + _sp_sh_ts1_set.clear(); + _sp_sh_time_walk_set.clear(); + _sp_sh_prop_delay_set.clear(); + _sp_sh_cable_length_ts0_set.clear(); + _sp_sh_calib_offset_ts0_set.clear(); + _sp_sh_cable_length_ts1_set.clear(); + _sp_sh_calib_offset_ts1_set.clear(); +} + +void sbnd::crt::CRTTimingAnalysis::ResizeSPSHVecs(const unsigned n) +{ + _sp_sh_channel_set.resize(n); + _sp_sh_mac5_set.resize(n); + _sp_sh_timing_chain_set.resize(n); + _sp_sh_ts0_set.resize(n); + _sp_sh_ts1_set.resize(n); + _sp_sh_time_walk_set.resize(n); + _sp_sh_prop_delay_set.resize(n); + _sp_sh_cable_length_ts0_set.resize(n); + _sp_sh_calib_offset_ts0_set.resize(n); + _sp_sh_cable_length_ts1_set.resize(n); + _sp_sh_calib_offset_ts1_set.resize(n); +} + +double sbnd::crt::CRTTimingAnalysis::IntrinsicResolution(const std::vector &_sp_sh_channel_set, + const std::vector &_sp_sh_ts_set, + const std::vector &_sp_sh_time_walk_set, + const std::vector &_sp_sh_prop_delay_set) +{ + struct SH { + int32_t channel; + double ts; + }; + + std::vector shs; + + for(unsigned i = 0; i < _sp_sh_channel_set.size(); ++i) + shs.push_back(SH({_sp_sh_channel_set[i], _sp_sh_ts_set[i] - _sp_sh_time_walk_set[i] - _sp_sh_prop_delay_set[i]})); + + std::sort(shs.begin(), shs.end(), [](auto &a, auto &b) + { return a.channel < b.channel; }); + + double sum = 0.; + + for(unsigned int i = 0; i < shs.size(); ++i) + { + for(unsigned int ii = i + 1; ii < shs.size(); ++ii) + sum += (shs[i].ts - shs[ii].ts); + } + + sum /= (shs.size() - 1); + + return sum; } void sbnd::crt::CRTTimingAnalysis::AnalyseCRTTracks(const std::vector> &CRTTrackVec, From 0f58321cb1ad6da6fc22f3de1c1ab63569c8b78c Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Wed, 25 Feb 2026 05:58:47 -0600 Subject: [PATCH 55/75] Add track content to CRTTimingAnalysis module, plus a few bugfixes to make run-able --- .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 400 ++++++++++++------ 1 file changed, 273 insertions(+), 127 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index 8b23a9699..482eb5d2d 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -40,6 +40,8 @@ namespace sbnd::crt { class CRTTimingAnalysis; + + constexpr double c = 3.3356e-2; // ns / cm } class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { @@ -57,6 +59,8 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { // Required functions. void analyze(art::Event const& e) override; + void ResetMaps(); + void AnalysePTBs(std::vector> &PTBVec); void AnalyseTDCs(std::vector> &TDCVec); @@ -77,10 +81,10 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { const std::vector &_sp_sh_prop_delay_set); void AnalyseCRTTracks(const std::vector> &CRTTrackVec, - const art::FindManyP &tracksToSpacePoints, - const art::FindOneP &spacepointsToClusters, - const art::FindManyP &clustersToStripHits); - + const art::FindManyP &tracksToSpacePoints); + + void ResetTrVariables(); + void AnalyseTPCSlices(const std::vector> &TPCSliceVec, const art::FindManyP &sliceToCorrectedOpFlashes, const art::FindManyP &sliceToPFPs, @@ -192,10 +196,12 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { int16_t _tr_tagger3; int16_t _tr_start_tagger; double _tr_start_dts0; + double _tr_start_dts1; bool _tr_start_single_timing_chain; int16_t _tr_start_timing_chain; int16_t _tr_end_tagger; double _tr_end_dts0; + double _tr_end_dts1; bool _tr_end_single_timing_chain; int16_t _tr_end_timing_chain; @@ -215,6 +221,12 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { double _tpc_crt_sp_ts1_rwm_ref; double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref; double _tpc_crt_sp_dts1; + + // Maps + std::map fSPTaggerMap; + std::map fSPdTs0Map; + std::map fSPdTs1Map; + std::map fSPTimingChainMap; }; sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) @@ -233,41 +245,43 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fCRTSpacePointMatchingModuleLabel = p.get("CRTSpacePointMatchingModuleLabel"); fAllowedPTBHLTs = p.get>("AllowedPTBHLTs"); + fCRTCalibrationDatabaseService = lar::providerFrom(); + art::ServiceHandle fs; fSPTree = fs->make("spacepoints",""); - fSPTree->Branch("run", "int", &_run); - fSPTree->Branch("subrun", "int", &_subrun); - fSPTree->Branch("event", "int", &_event); - fSPTree->Branch("crt_timing_reference_type", "int", &_crt_timing_reference_type); - fSPTree->Branch("crt_timing_reference_channel", "int", &_crt_timing_reference_channel); - - fSPTree->Branch("etrig_good", "bool", &_etrig_good); - fSPTree->Branch("rwm_good", "bool", &_rwm_good); - fSPTree->Branch("ptb_hlt_beam_gate_good", "bool", &_ptb_hlt_beam_gate_good); - fSPTree->Branch("crt_t1_reset_good", "bool", &_crt_t1_reset_good); - fSPTree->Branch("rwm_etrig_diff", "double", &_rwm_etrig_diff); - fSPTree->Branch("ptb_hlt_beam_gate_etrig_diff", "double", &_ptb_hlt_beam_gate_etrig_diff); - fSPTree->Branch("rwm_crt_t1_reset_diff", "double", &_rwm_crt_t1_reset_diff); - fSPTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", "double", &_ptb_hlt_beam_gate_crt_t1_reset_diff); - fSPTree->Branch("rwm_ptb_hlt_beam_gate_diff", "double", &_rwm_ptb_hlt_beam_gate_diff); - - fSPTree->Branch("sp_nhits", "uint16_t", &_sp_nhits); - fSPTree->Branch("sp_tagger", "int16_t", &_sp_tagger); - fSPTree->Branch("sp_x", "double", &_sp_x); - fSPTree->Branch("sp_y", "double", &_sp_y); - fSPTree->Branch("sp_z", "double", &_sp_z); - fSPTree->Branch("sp_pe", "double", &_sp_pe); - fSPTree->Branch("sp_ts0", "double", &_sp_ts0); - fSPTree->Branch("sp_ts0_rwm_ref", "double", &_sp_ts0_rwm_ref); - fSPTree->Branch("sp_ts0_ptb_hlt_beam_gate_ref", "double", &_sp_ts0_ptb_hlt_beam_gate_ref); - fSPTree->Branch("sp_dts0", "double", &_sp_dts0); - fSPTree->Branch("sp_ts1", "double", &_sp_ts1); - fSPTree->Branch("sp_ts1_rwm_ref", "double", &_sp_ts1_rwm_ref); - fSPTree->Branch("sp_ts1_ptb_hlt_beam_gate_ref", "double", &_sp_ts1_ptb_hlt_beam_gate_ref); - fSPTree->Branch("sp_dts1", "double", &_sp_dts1); - fSPTree->Branch("sp_single_timing_chain", "bool", &_sp_single_timing_chain); - fSPTree->Branch("sp_timing_chain", "int16_t", &_sp_timing_chain); + fSPTree->Branch("run", &_run); + fSPTree->Branch("subrun", &_subrun); + fSPTree->Branch("event", &_event); + fSPTree->Branch("crt_timing_reference_type", &_crt_timing_reference_type); + fSPTree->Branch("crt_timing_reference_channel", &_crt_timing_reference_channel); + + fSPTree->Branch("etrig_good", &_etrig_good); + fSPTree->Branch("rwm_good", &_rwm_good); + fSPTree->Branch("ptb_hlt_beam_gate_good", &_ptb_hlt_beam_gate_good); + fSPTree->Branch("crt_t1_reset_good", &_crt_t1_reset_good); + fSPTree->Branch("rwm_etrig_diff", &_rwm_etrig_diff); + fSPTree->Branch("ptb_hlt_beam_gate_etrig_diff", &_ptb_hlt_beam_gate_etrig_diff); + fSPTree->Branch("rwm_crt_t1_reset_diff", &_rwm_crt_t1_reset_diff); + fSPTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fSPTree->Branch("rwm_ptb_hlt_beam_gate_diff", &_rwm_ptb_hlt_beam_gate_diff); + + fSPTree->Branch("sp_nhits", &_sp_nhits); + fSPTree->Branch("sp_tagger", &_sp_tagger); + fSPTree->Branch("sp_x", &_sp_x); + fSPTree->Branch("sp_y", &_sp_y); + fSPTree->Branch("sp_z", &_sp_z); + fSPTree->Branch("sp_pe", &_sp_pe); + fSPTree->Branch("sp_ts0", &_sp_ts0); + fSPTree->Branch("sp_ts0_rwm_ref", &_sp_ts0_rwm_ref); + fSPTree->Branch("sp_ts0_ptb_hlt_beam_gate_ref", &_sp_ts0_ptb_hlt_beam_gate_ref); + fSPTree->Branch("sp_dts0", &_sp_dts0); + fSPTree->Branch("sp_ts1", &_sp_ts1); + fSPTree->Branch("sp_ts1_rwm_ref", &_sp_ts1_rwm_ref); + fSPTree->Branch("sp_ts1_ptb_hlt_beam_gate_ref", &_sp_ts1_ptb_hlt_beam_gate_ref); + fSPTree->Branch("sp_dts1", &_sp_dts1); + fSPTree->Branch("sp_single_timing_chain", &_sp_single_timing_chain); + fSPTree->Branch("sp_timing_chain", &_sp_timing_chain); fSPTree->Branch("sp_sh_channel_set", "std::vector", &_sp_sh_channel_set); fSPTree->Branch("sp_sh_mac5_set", "std::vector", &_sp_sh_mac5_set); fSPTree->Branch("sp_sh_timing_chain_set", "std::vector", &_sp_sh_timing_chain_set); @@ -281,96 +295,100 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fSPTree->Branch("sp_sh_calib_offset_ts1_set", "std::vector", &_sp_sh_calib_offset_ts1_set); fTrTree = fs->make("tracks",""); - fTrTree->Branch("run", "int", &_run); - fTrTree->Branch("subrun", "int", &_subrun); - fTrTree->Branch("event", "int", &_event); - fTrTree->Branch("crt_timing_reference_type", "int", &_crt_timing_reference_type); - fTrTree->Branch("crt_timing_reference_channel", "int", &_crt_timing_reference_channel); - - fTrTree->Branch("etrig_good", "bool", &_etrig_good); - fTrTree->Branch("rwm_good", "bool", &_rwm_good); - fTrTree->Branch("ptb_hlt_beam_gate_good", "bool", &_ptb_hlt_beam_gate_good); - fTrTree->Branch("crt_t1_reset_good", "bool", &_crt_t1_reset_good); - fTrTree->Branch("rwm_etrig_diff", "double", &_rwm_etrig_diff); - fTrTree->Branch("ptb_hlt_beam_gate_etrig_diff", "double", &_ptb_hlt_beam_gate_etrig_diff); - fTrTree->Branch("rwm_crt_t1_reset_diff", "double", &_rwm_crt_t1_reset_diff); - fTrTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", "double", &_ptb_hlt_beam_gate_crt_t1_reset_diff); - fTrTree->Branch("rwm_ptb_hlt_beam_gate_diff", "double", &_rwm_ptb_hlt_beam_gate_diff); - - fTrTree->Branch("tr_start_x", "double", &_tr_start_x); - fTrTree->Branch("tr_start_y", "double", &_tr_start_y); - fTrTree->Branch("tr_start_z", "double", &_tr_start_z); - fTrTree->Branch("tr_end_x", "double", &_tr_end_x); - fTrTree->Branch("tr_end_y", "double", &_tr_end_y); - fTrTree->Branch("tr_end_z", "double", &_tr_end_z); - fTrTree->Branch("tr_dir_x", "double", &_tr_dir_x); - fTrTree->Branch("tr_dir_y", "double", &_tr_dir_y); - fTrTree->Branch("tr_dir_z", "double", &_tr_dir_z); - fTrTree->Branch("tr_ts0", "double", &_tr_ts0); - fTrTree->Branch("tr_ts0_rwm_ref", "double", &_tr_ts0_rwm_ref); - fTrTree->Branch("tr_ts0_ptb_hlt_beam_gate_ref", "double", &_tr_ts0_ptb_hlt_beam_gate_ref); - fTrTree->Branch("tr_ts1", "double", &_tr_ts1); - fTrTree->Branch("tr_ts1_rwm_ref", "double", &_tr_ts1_rwm_ref); - fTrTree->Branch("tr_ts1_ptb_hlt_beam_gate_ref", "double", &_tr_ts1_ptb_hlt_beam_gate_ref); - fTrTree->Branch("tr_pe", "double", &_tr_pe); - fTrTree->Branch("tr_length", "double", &_tr_length); - fTrTree->Branch("tr_length_tof", "double", &_tr_length_tof); - fTrTree->Branch("tr_tof_ts0", "double", &_tr_tof_ts0); - fTrTree->Branch("tr_tof_diff_ts0", "double", &_tr_tof_diff_ts0); - fTrTree->Branch("tr_tof_ts1", "double", &_tr_tof_ts1); - fTrTree->Branch("tr_tof_diff_ts1", "double", &_tr_tof_diff_ts1); - fTrTree->Branch("tr_theta", "double", &_tr_theta); - fTrTree->Branch("tr_phi", "double", &_tr_phi); - fTrTree->Branch("tr_triple", "bool", &_tr_triple); - fTrTree->Branch("tr_tagger1", "int16_t", &_tr_tagger1); - fTrTree->Branch("tr_tagger2", "int16_t", &_tr_tagger2); - fTrTree->Branch("tr_tagger3", "int16_t", &_tr_tagger3); - fTrTree->Branch("tr_start_tagger", "int16_t", &_tr_start_tagger); - fTrTree->Branch("tr_start_dts0", "double", &_tr_start_dts0); - fTrTree->Branch("tr_start_single_timing_chain", "bool", &_tr_start_single_timing_chain); - fTrTree->Branch("tr_start_timing_chain", "int16_t", &_tr_start_timing_chain); - fTrTree->Branch("tr_end_tagger", "int16_t", &_tr_end_tagger); - fTrTree->Branch("tr_end_dts0", "double", &_tr_end_dts0); - fTrTree->Branch("tr_end_single_timing_chain", "bool", &_tr_end_single_timing_chain); - fTrTree->Branch("tr_end_timing_chain", "int16_t", &_tr_end_timing_chain); + fTrTree->Branch("run", &_run); + fTrTree->Branch("subrun", &_subrun); + fTrTree->Branch("event", &_event); + fTrTree->Branch("crt_timing_reference_type", &_crt_timing_reference_type); + fTrTree->Branch("crt_timing_reference_channel", &_crt_timing_reference_channel); + + fTrTree->Branch("etrig_good", &_etrig_good); + fTrTree->Branch("rwm_good", &_rwm_good); + fTrTree->Branch("ptb_hlt_beam_gate_good", &_ptb_hlt_beam_gate_good); + fTrTree->Branch("crt_t1_reset_good", &_crt_t1_reset_good); + fTrTree->Branch("rwm_etrig_diff", &_rwm_etrig_diff); + fTrTree->Branch("ptb_hlt_beam_gate_etrig_diff", &_ptb_hlt_beam_gate_etrig_diff); + fTrTree->Branch("rwm_crt_t1_reset_diff", &_rwm_crt_t1_reset_diff); + fTrTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fTrTree->Branch("rwm_ptb_hlt_beam_gate_diff", &_rwm_ptb_hlt_beam_gate_diff); + + fTrTree->Branch("tr_start_x", &_tr_start_x); + fTrTree->Branch("tr_start_y", &_tr_start_y); + fTrTree->Branch("tr_start_z", &_tr_start_z); + fTrTree->Branch("tr_end_x", &_tr_end_x); + fTrTree->Branch("tr_end_y", &_tr_end_y); + fTrTree->Branch("tr_end_z", &_tr_end_z); + fTrTree->Branch("tr_dir_x", &_tr_dir_x); + fTrTree->Branch("tr_dir_y", &_tr_dir_y); + fTrTree->Branch("tr_dir_z", &_tr_dir_z); + fTrTree->Branch("tr_ts0", &_tr_ts0); + fTrTree->Branch("tr_ts0_rwm_ref", &_tr_ts0_rwm_ref); + fTrTree->Branch("tr_ts0_ptb_hlt_beam_gate_ref", &_tr_ts0_ptb_hlt_beam_gate_ref); + fTrTree->Branch("tr_ts1", &_tr_ts1); + fTrTree->Branch("tr_ts1_rwm_ref", &_tr_ts1_rwm_ref); + fTrTree->Branch("tr_ts1_ptb_hlt_beam_gate_ref", &_tr_ts1_ptb_hlt_beam_gate_ref); + fTrTree->Branch("tr_pe", &_tr_pe); + fTrTree->Branch("tr_length", &_tr_length); + fTrTree->Branch("tr_length_tof", &_tr_length_tof); + fTrTree->Branch("tr_tof_ts0", &_tr_tof_ts0); + fTrTree->Branch("tr_tof_diff_ts0", &_tr_tof_diff_ts0); + fTrTree->Branch("tr_tof_ts1", &_tr_tof_ts1); + fTrTree->Branch("tr_tof_diff_ts1", &_tr_tof_diff_ts1); + fTrTree->Branch("tr_theta", &_tr_theta); + fTrTree->Branch("tr_phi", &_tr_phi); + fTrTree->Branch("tr_triple", &_tr_triple); + fTrTree->Branch("tr_tagger1", &_tr_tagger1); + fTrTree->Branch("tr_tagger2", &_tr_tagger2); + fTrTree->Branch("tr_tagger3", &_tr_tagger3); + fTrTree->Branch("tr_start_tagger", &_tr_start_tagger); + fTrTree->Branch("tr_start_dts0", &_tr_start_dts0); + fTrTree->Branch("tr_start_dts1", &_tr_start_dts1); + fTrTree->Branch("tr_start_single_timing_chain", &_tr_start_single_timing_chain); + fTrTree->Branch("tr_start_timing_chain", &_tr_start_timing_chain); + fTrTree->Branch("tr_end_tagger", &_tr_end_tagger); + fTrTree->Branch("tr_end_dts0", &_tr_end_dts0); + fTrTree->Branch("tr_end_dts1", &_tr_end_dts1); + fTrTree->Branch("tr_end_single_timing_chain", &_tr_end_single_timing_chain); + fTrTree->Branch("tr_end_timing_chain", &_tr_end_timing_chain); fTPCTree = fs->make("slices",""); - fTPCTree->Branch("run", "int", &_run); - fTPCTree->Branch("subrun", "int", &_subrun); - fTPCTree->Branch("event", "int", &_event); - fTPCTree->Branch("crt_timing_reference_type", "int", &_crt_timing_reference_type); - fTPCTree->Branch("crt_timing_reference_channel", "int", &_crt_timing_reference_channel); - - fTPCTree->Branch("etrig_good", "bool", &_etrig_good); - fTPCTree->Branch("rwm_good", "bool", &_rwm_good); - fTPCTree->Branch("ptb_hlt_beam_gate_good", "bool", &_ptb_hlt_beam_gate_good); - fTPCTree->Branch("crt_t1_reset_good", "bool", &_crt_t1_reset_good); - fTPCTree->Branch("rwm_etrig_diff", "double", &_rwm_etrig_diff); - fTPCTree->Branch("ptb_hlt_beam_gate_etrig_diff", "double", &_ptb_hlt_beam_gate_etrig_diff); - fTPCTree->Branch("rwm_crt_t1_reset_diff", "double", &_rwm_crt_t1_reset_diff); - fTPCTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", "double", &_ptb_hlt_beam_gate_crt_t1_reset_diff); - fTPCTree->Branch("rwm_ptb_hlt_beam_gate_diff", "double", &_rwm_ptb_hlt_beam_gate_diff); - - fTPCTree->Branch("tpc_has_corrected_opflash", "bool", &_tpc_has_corrected_opflash); - fTPCTree->Branch("tpc_has_crt_sp_match", "bool", &_tpc_has_crt_sp_match); - fTPCTree->Branch("tpc_opflash_t0", "double", &_tpc_opflash_t0); - fTPCTree->Branch("tpc_opflash_nutof_light", "double", &_tpc_opflash_nutof_light); - fTPCTree->Branch("tpc_opflash_nutof_charge", "double", &_tpc_opflash_nutof_charge); - fTPCTree->Branch("tpc_opflash_t0_corrected", "double", &_tpc_opflash_t0_corrected); - fTPCTree->Branch("tpc_opflash_t0_corrected_rwm", "double", &_tpc_opflash_t0_corrected_rwm); - fTPCTree->Branch("tpc_crt_sp_score", "double", &_tpc_crt_sp_score); - fTPCTree->Branch("tpc_crt_sp_ts0", "double", &_tpc_crt_sp_ts0); - fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref", "double", &_tpc_crt_sp_ts0_rwm_ref); - fTPCTree->Branch("tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref", "double", &_tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref); - fTPCTree->Branch("tpc_crt_sp_dts0", "double", &_tpc_crt_sp_dts0); - fTPCTree->Branch("tpc_crt_sp_ts1", "double", &_tpc_crt_sp_ts1); - fTPCTree->Branch("tpc_crt_sp_ts1_rwm_ref", "double", &_tpc_crt_sp_ts1_rwm_ref); - fTPCTree->Branch("tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref", "double", &_tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref); - fTPCTree->Branch("tpc_crt_sp_dts1", "double", &_tpc_crt_sp_dts1); + fTPCTree->Branch("run", &_run); + fTPCTree->Branch("subrun", &_subrun); + fTPCTree->Branch("event", &_event); + fTPCTree->Branch("crt_timing_reference_type", &_crt_timing_reference_type); + fTPCTree->Branch("crt_timing_reference_channel", &_crt_timing_reference_channel); + + fTPCTree->Branch("etrig_good", &_etrig_good); + fTPCTree->Branch("rwm_good", &_rwm_good); + fTPCTree->Branch("ptb_hlt_beam_gate_good", &_ptb_hlt_beam_gate_good); + fTPCTree->Branch("crt_t1_reset_good", &_crt_t1_reset_good); + fTPCTree->Branch("rwm_etrig_diff", &_rwm_etrig_diff); + fTPCTree->Branch("ptb_hlt_beam_gate_etrig_diff", &_ptb_hlt_beam_gate_etrig_diff); + fTPCTree->Branch("rwm_crt_t1_reset_diff", &_rwm_crt_t1_reset_diff); + fTPCTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", &_ptb_hlt_beam_gate_crt_t1_reset_diff); + fTPCTree->Branch("rwm_ptb_hlt_beam_gate_diff", &_rwm_ptb_hlt_beam_gate_diff); + + fTPCTree->Branch("tpc_has_corrected_opflash", &_tpc_has_corrected_opflash); + fTPCTree->Branch("tpc_has_crt_sp_match", &_tpc_has_crt_sp_match); + fTPCTree->Branch("tpc_opflash_t0", &_tpc_opflash_t0); + fTPCTree->Branch("tpc_opflash_nutof_light", &_tpc_opflash_nutof_light); + fTPCTree->Branch("tpc_opflash_nutof_charge", &_tpc_opflash_nutof_charge); + fTPCTree->Branch("tpc_opflash_t0_corrected", &_tpc_opflash_t0_corrected); + fTPCTree->Branch("tpc_opflash_t0_corrected_rwm", &_tpc_opflash_t0_corrected_rwm); + fTPCTree->Branch("tpc_crt_sp_score", &_tpc_crt_sp_score); + fTPCTree->Branch("tpc_crt_sp_ts0", &_tpc_crt_sp_ts0); + fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref", &_tpc_crt_sp_ts0_rwm_ref); + fTPCTree->Branch("tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref", &_tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref); + fTPCTree->Branch("tpc_crt_sp_dts0", &_tpc_crt_sp_dts0); + fTPCTree->Branch("tpc_crt_sp_ts1", &_tpc_crt_sp_ts1); + fTPCTree->Branch("tpc_crt_sp_ts1_rwm_ref", &_tpc_crt_sp_ts1_rwm_ref); + fTPCTree->Branch("tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref", &_tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref); + fTPCTree->Branch("tpc_crt_sp_dts1", &_tpc_crt_sp_dts1); } void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) { + ResetMaps(); + _run = e.id().run(); _subrun = e.id().subRun(); _event = e.id().event(); @@ -455,7 +473,7 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) art::FindManyP tracksToSpacePoints(CRTTrackHandle, e, fCRTTrackModuleLabel); // Fill CRTTrack variables - AnalyseCRTTracks(CRTTrackVec, tracksToSpacePoints, spacepointsToClusters, clustersToStripHits); + AnalyseCRTTracks(CRTTrackVec, tracksToSpacePoints); // Get TPCSlices art::Handle> TPCSliceHandle; @@ -498,6 +516,14 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) AnalyseTPCSlices(TPCSliceVec, sliceToCorrectedOpFlashes, sliceToPFPs, pfpToTrack, trackToCRTSpacePoint, spacepointsToClusters, clustersToStripHits); } +void sbnd::crt::CRTTimingAnalysis::ResetMaps() +{ + fSPTaggerMap.clear(); + fSPdTs0Map.clear(); + fSPdTs1Map.clear(); + fSPTimingChainMap.clear(); +} + void sbnd::crt::CRTTimingAnalysis::AnalysePTBs(std::vector> &PTBVec) { unsigned nHLTs = 0; @@ -709,6 +735,11 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vectorFill(); + + fSPTaggerMap[sp.key()] = _sp_tagger; + fSPdTs0Map[sp.key()] = _sp_dts0; + fSPdTs1Map[sp.key()] = _sp_dts1; + fSPTimingChainMap[sp.key()] = _sp_timing_chain; } } @@ -716,7 +747,8 @@ void sbnd::crt::CRTTimingAnalysis::ResetSPVariables() { _sp_nhits = std::numeric_limits::max(); - _sp_tagger = CRTTagger::kUndefinedTagger; + _sp_tagger = std::numeric_limits::lowest(); + _sp_timing_chain = std::numeric_limits::lowest(); _sp_x = std::numeric_limits::lowest(); _sp_y = std::numeric_limits::lowest(); @@ -733,8 +765,6 @@ void sbnd::crt::CRTTimingAnalysis::ResetSPVariables() _sp_single_timing_chain = false; - _sp_timing_chain = std::numeric_limits::lowest(); - _sp_sh_channel_set.clear(); _sp_sh_mac5_set.clear(); _sp_sh_timing_chain_set.clear(); @@ -795,10 +825,126 @@ double sbnd::crt::CRTTimingAnalysis::IntrinsicResolution(const std::vector> &CRTTrackVec, - const art::FindManyP &tracksToSpacePoints, - const art::FindOneP &spacepointsToClusters, - const art::FindManyP &clustersToStripHits) + const art::FindManyP &tracksToSpacePoints) +{ + for(auto const &tr : CRTTrackVec) + { + _tr_start_x = tr->Start().X(); + _tr_start_y = tr->Start().Y(); + _tr_start_z = tr->Start().Z(); + _tr_end_x = tr->End().X(); + _tr_end_y = tr->End().Y(); + _tr_end_z = tr->End().Z(); + _tr_dir_x = tr->Direction().X(); + _tr_dir_y = tr->Direction().Y(); + _tr_dir_z = tr->Direction().Z(); + _tr_ts0 = tr->Ts0(); + _tr_ts0_rwm_ref = _tr_ts0 + _rwm_etrig_diff; + _tr_ts0_ptb_hlt_beam_gate_ref = _tr_ts0 + _ptb_hlt_beam_gate_etrig_diff; + _tr_ts1 = tr->Ts1(); + _tr_ts1_rwm_ref = _tr_ts1 + _rwm_crt_t1_reset_diff; + _tr_ts1_ptb_hlt_beam_gate_ref = _tr_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; + _tr_pe = tr->PE(); + _tr_length = tr->Length(); + _tr_length_tof = _tr_length * c; + _tr_theta = tr->Theta(); + _tr_phi = tr->Phi(); + _tr_triple = tr->Triple(); + _tr_tagger1 = tr->Taggers()[0]; + _tr_tagger2 = tr->Taggers()[1]; + + if(_tr_triple) + _tr_tagger3 = tr->Taggers()[2]; + + std::vector> sps = tracksToSpacePoints.at(tr.key()); + std::sort(sps.begin(), sps.end(), [](auto &a, auto &b) + { return a->Ts0() < b->Ts0(); }); + + if((_tr_triple && sps.size() != 3) || (!_tr_triple && sps.size() != 2)) + { + const int expectation = _tr_triple ? 3 : 2; + std::cout << "CRTSpacePoint vector wrong size (" << sps.size() + << ") for track expectation (" << expectation << ")" << std::endl; + throw std::exception(); + } + + const art::Ptr start = sps[0]; + const art::Ptr end = _tr_triple ? sps[2] : sps[1]; + + _tr_tof_ts0 = end->Ts0() - start->Ts0(); + _tr_tof_diff_ts0 = _tr_tof_ts0 - _tr_length_tof; + _tr_tof_ts1 = end->Ts1() - start->Ts1(); + _tr_tof_diff_ts1 = _tr_tof_ts1 - _tr_length_tof; + _tr_start_tagger = fSPTaggerMap[start.key()]; + _tr_start_dts0 = fSPdTs0Map[start.key()]; + _tr_start_dts1 = fSPdTs1Map[start.key()]; + _tr_start_timing_chain = fSPTimingChainMap[start.key()]; + _tr_start_single_timing_chain = _tr_start_timing_chain != -1; + _tr_end_tagger = fSPTaggerMap[end.key()]; + _tr_end_dts0 = fSPdTs0Map[end.key()]; + _tr_end_dts1 = fSPdTs1Map[end.key()]; + _tr_end_timing_chain = fSPTimingChainMap[end.key()]; + _tr_end_single_timing_chain = _tr_end_timing_chain != -1; + + if(_tr_start_tagger != _tr_tagger1) + { + std::cout << "CRTTrack start tagger inconsistent between direct access (" << _tr_tagger1 + << ") and associated CRTSpacePoint (" << _tr_start_tagger << ")" << std::endl; + throw std::exception(); + } + + if((_tr_triple && _tr_end_tagger != _tr_tagger3) || (!_tr_triple && _tr_end_tagger != _tr_tagger2)) + { + const int expectation = _tr_triple ? _tr_tagger3 : _tr_tagger2; + std::cout << "CRTTrack end tagger inconsistent between direct access (" << expectation + << ") and associated CRTSpacePoint (" << _tr_end_tagger << ")" << std::endl; + throw std::exception(); + } + } +} + +void sbnd::crt::CRTTimingAnalysis::ResetTrVariables() { + _tr_start_x = std::numeric_limits::lowest(); + _tr_start_y = std::numeric_limits::lowest(); + _tr_start_z = std::numeric_limits::lowest(); + _tr_end_x = std::numeric_limits::lowest(); + _tr_end_y = std::numeric_limits::lowest(); + _tr_end_z = std::numeric_limits::lowest(); + _tr_dir_x = std::numeric_limits::lowest(); + _tr_dir_y = std::numeric_limits::lowest(); + _tr_dir_z = std::numeric_limits::lowest(); + _tr_ts0 = std::numeric_limits::lowest(); + _tr_ts0_rwm_ref = std::numeric_limits::lowest(); + _tr_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _tr_ts1 = std::numeric_limits::lowest(); + _tr_ts1_rwm_ref = std::numeric_limits::lowest(); + _tr_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _tr_pe = std::numeric_limits::lowest(); + _tr_length = std::numeric_limits::lowest(); + _tr_length_tof = std::numeric_limits::lowest(); + _tr_tof_ts0 = std::numeric_limits::lowest(); + _tr_tof_diff_ts0 = std::numeric_limits::lowest(); + _tr_tof_ts1 = std::numeric_limits::lowest(); + _tr_tof_diff_ts1 = std::numeric_limits::lowest(); + _tr_theta = std::numeric_limits::lowest(); + _tr_phi = std::numeric_limits::lowest(); + _tr_start_dts0 = std::numeric_limits::lowest(); + _tr_start_dts1 = std::numeric_limits::lowest(); + _tr_end_dts0 = std::numeric_limits::lowest(); + _tr_end_dts1 = std::numeric_limits::lowest(); + + _tr_triple = false; + _tr_start_single_timing_chain = false; + _tr_end_single_timing_chain = false; + + _tr_tagger1 = std::numeric_limits::lowest(); + _tr_tagger2 = std::numeric_limits::lowest(); + _tr_tagger3 = std::numeric_limits::lowest(); + _tr_start_tagger = std::numeric_limits::lowest(); + _tr_start_timing_chain = std::numeric_limits::lowest(); + _tr_end_tagger = std::numeric_limits::lowest(); + _tr_end_timing_chain = std::numeric_limits::lowest(); } void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vector> &TPCSliceVec, From 1ca6df619557c004581a6b631c88fdcfce169986 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Wed, 25 Feb 2026 05:59:50 -0600 Subject: [PATCH 56/75] Make fcl changes to run CRTTimingAnalysis --- sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl | 5 +++- sbndcode/CRT/CRTAna/run_crttimingana_data.fcl | 28 +++++++++++++++++++ .../CRT/CRTReco/crtrecoproducers_sbnd.fcl | 5 +++- 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 sbndcode/CRT/CRTAna/run_crttimingana_data.fcl diff --git a/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl b/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl index 4a9bff36a..406e07264 100644 --- a/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl +++ b/sbndcode/CRT/CRTAna/crttimingana_sbnd.fcl @@ -1,6 +1,8 @@ +#include "crtrecoproducers_sbnd.fcl" + BEGIN_PROLOG -crttophatana_data_sbnd: +crttimingana_data_sbnd: { module_type: "CRTTimingAnalysis" CRTClusterModuleLabel: "crtclustering" @@ -14,6 +16,7 @@ crttophatana_data_sbnd: TPCTrackModuleLabel: "pandoraSCETrack" CRTSpacePointMatchingModuleLabel: "crtspacepointmatchingSCE" AllowedPTBHLTs: [ 26, 27 ] + CRTClusterCharacterisationAlg: @local::crtclustercharacterisationalg_data_sbnd } END_PROLOG diff --git a/sbndcode/CRT/CRTAna/run_crttimingana_data.fcl b/sbndcode/CRT/CRTAna/run_crttimingana_data.fcl new file mode 100644 index 000000000..bcdcfd52a --- /dev/null +++ b/sbndcode/CRT/CRTAna/run_crttimingana_data.fcl @@ -0,0 +1,28 @@ +#include "services_sbnd.fcl" +#include "crt_services_sbnd.fcl" +#include "crttimingana_sbnd.fcl" + +process_name: CRTTimingAna + +services: +{ + TFileService: { fileName: "crttimingana_sbnd.root" } + @table::sbnd_basic_services + @table::crt_services_data_sbnd +} + +source: +{ + module_type: RootInput +} + +physics: +{ + analyzers: + { + crttimingana: @local::crttimingana_data_sbnd + } + + ana: [ crttimingana ] + end_paths: [ ana ] +} diff --git a/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl b/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl index 0b4ca1c3c..cbfd1a765 100644 --- a/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl +++ b/sbndcode/CRT/CRTReco/crtrecoproducers_sbnd.fcl @@ -54,6 +54,9 @@ crtclustercharacterisationalg_sbnd: TimeWalkScale: @local::sbnd_crtsim.DetSimParams.TDelayScale } +crtclustercharacterisationalg_data_sbnd: @local::crtclustercharacterisationalg_sbnd +crtclustercharacterisationalg_data_sbnd.TimeOffset: 0 + crtspacepointproducer_sbnd: { ClusterCharacterisationAlg: @local::crtclustercharacterisationalg_sbnd @@ -62,7 +65,7 @@ crtspacepointproducer_sbnd: } crtspacepointproducer_data_sbnd: @local::crtspacepointproducer_sbnd -crtspacepointproducer_data_sbnd.ClusterCharacterisationAlg.TimeOffset: 0 +crtspacepointproducer_data_sbnd.ClusterCharacterisationAlg: @local::crtclustercharacterisationalg_data_sbnd crttrackproducer_sbnd: { From 8f8b77b96957c868c88f89574991980af937a8ca Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Wed, 25 Feb 2026 06:00:12 -0600 Subject: [PATCH 57/75] Make sure timing chain map is installed to path --- sbndcode/ChannelMaps/CRT/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbndcode/ChannelMaps/CRT/CMakeLists.txt b/sbndcode/ChannelMaps/CRT/CMakeLists.txt index b67ef20a5..9e6a43cfa 100644 --- a/sbndcode/ChannelMaps/CRT/CMakeLists.txt +++ b/sbndcode/ChannelMaps/CRT/CMakeLists.txt @@ -2,7 +2,7 @@ install_headers() install_fhicl() install_source() -file(GLOB channel_map_file *ChannelMap*.txt) +file(GLOB channel_map_file *Map*.txt) install_fw( LIST ${channel_map_file} ) art_make(SERVICE_LIBRARIES From cacb8d84ef0969173ad11cfa043ec67f633d36ff Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Wed, 25 Feb 2026 08:30:23 -0600 Subject: [PATCH 58/75] Add TPC slice based variables --- .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 98 ++++++++++++++++--- 1 file changed, 84 insertions(+), 14 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index 482eb5d2d..bc2795de2 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -41,7 +41,8 @@ namespace sbnd::crt { class CRTTimingAnalysis; - constexpr double c = 3.3356e-2; // ns / cm + constexpr double fSpeedOfLightNanosecondPerCentimeter = 3.3356e-2; // ns / cm + constexpr double fMicrosecondToNanosecond = 1e3; // ns } class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { @@ -86,12 +87,12 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { void ResetTrVariables(); void AnalyseTPCSlices(const std::vector> &TPCSliceVec, - const art::FindManyP &sliceToCorrectedOpFlashes, + const art::FindOneP &sliceToCorrectedOpFlash, const art::FindManyP &sliceToPFPs, const art::FindOneP &pfpToTrack, - const art::FindOneP &trackToCRTSpacePoint, - const art::FindOneP &spacepointsToClusters, - const art::FindManyP &clustersToStripHits); + const art::FindOneP &trackToCRTSpacePoint); + + void ResetTPCVariables(); private: @@ -211,7 +212,8 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { double _tpc_opflash_nutof_light; double _tpc_opflash_nutof_charge; double _tpc_opflash_t0_corrected; - double _tpc_opflash_t0_corrected_rwm; + double _tpc_opflash_interaction_time_rwm; + double _tpc_opflash_front_face_rwm; double _tpc_crt_sp_score; double _tpc_crt_sp_ts0; double _tpc_crt_sp_ts0_rwm_ref; @@ -373,7 +375,8 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fTPCTree->Branch("tpc_opflash_nutof_light", &_tpc_opflash_nutof_light); fTPCTree->Branch("tpc_opflash_nutof_charge", &_tpc_opflash_nutof_charge); fTPCTree->Branch("tpc_opflash_t0_corrected", &_tpc_opflash_t0_corrected); - fTPCTree->Branch("tpc_opflash_t0_corrected_rwm", &_tpc_opflash_t0_corrected_rwm); + fTPCTree->Branch("tpc_opflash_interaction_time_rwm", &_tpc_opflash_interaction_time_rwm); + fTPCTree->Branch("tpc_opflash_front_face_rwm", &_tpc_opflash_front_face_rwm); fTPCTree->Branch("tpc_crt_sp_score", &_tpc_crt_sp_score); fTPCTree->Branch("tpc_crt_sp_ts0", &_tpc_crt_sp_ts0); fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref", &_tpc_crt_sp_ts0_rwm_ref); @@ -486,7 +489,7 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) art::fill_ptr_vector(TPCSliceVec, TPCSliceHandle); // Get TPCSlice to CorrectedOpFlash Assns - art::FindManyP sliceToCorrectedOpFlashes(TPCSliceHandle, e, fCorrectedOpFlashModuleLabel); + art::FindOneP sliceToCorrectedOpFlash(TPCSliceHandle, e, fCorrectedOpFlashModuleLabel); // Get TPCSlice to PFP Assns art::FindManyP sliceToPFPs(TPCSliceHandle, e, fTPCSliceModuleLabel); @@ -513,7 +516,7 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) // Get Track to CRTSpacePoint Assns art::FindOneP trackToCRTSpacePoint(TPCTrackHandle, e, fCRTSpacePointMatchingModuleLabel); - AnalyseTPCSlices(TPCSliceVec, sliceToCorrectedOpFlashes, sliceToPFPs, pfpToTrack, trackToCRTSpacePoint, spacepointsToClusters, clustersToStripHits); + AnalyseTPCSlices(TPCSliceVec, sliceToCorrectedOpFlash, sliceToPFPs, pfpToTrack, trackToCRTSpacePoint); } void sbnd::crt::CRTTimingAnalysis::ResetMaps() @@ -829,6 +832,8 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTTracks(const std::vectorStart().X(); _tr_start_y = tr->Start().Y(); _tr_start_z = tr->Start().Z(); @@ -846,7 +851,7 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTTracks(const std::vectorPE(); _tr_length = tr->Length(); - _tr_length_tof = _tr_length * c; + _tr_length_tof = _tr_length * fSpeedOfLightNanosecondPerCentimeter; _tr_theta = tr->Theta(); _tr_phi = tr->Phi(); _tr_triple = tr->Triple(); @@ -900,6 +905,8 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTTracks(const std::vectorFill(); } } @@ -948,13 +955,76 @@ void sbnd::crt::CRTTimingAnalysis::ResetTrVariables() } void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vector> &TPCSliceVec, - const art::FindManyP &sliceToCorrectedOpFlashes, + const art::FindOneP &sliceToCorrectedOpFlash, const art::FindManyP &sliceToPFPs, const art::FindOneP &pfpToTrack, - const art::FindOneP &trackToCRTSpacePoint, - const art::FindOneP &spacepointsToClusters, - const art::FindManyP &clustersToStripHits) + const art::FindOneP &trackToCRTSpacePoint) +{ + for(auto const &sl : TPCSliceVec) + { + const art::Ptr copflash = sliceToCorrectedOpFlash.at(sl.key()); + + if(copflash.isNonnull()) + { + _tpc_has_corrected_opflash = true; + _tpc_opflash_t0 = copflash->OpFlashT0 * fMicrosecondToNanosecond; + _tpc_opflash_nutof_light = copflash->NuToFLight * fMicrosecondToNanosecond; + _tpc_opflash_nutof_charge = copflash->NuToFCharge * fMicrosecondToNanosecond; + _tpc_opflash_t0_corrected = copflash->OpFlashT0Corrected * fMicrosecondToNanosecond; + _tpc_opflash_interaction_time_rwm = _tpc_opflash_t0_corrected + 1738.; + _tpc_opflash_front_face_rwm = _tpc_opflash_interaction_time_rwm - _tpc_opflash_nutof_charge; + } + + const std::vector> pfps = sliceToPFPs.at(sl.key()); + + for(auto const &pfp : pfps) + { + const art::Ptr track = pfpToTrack.at(pfp.key()); + + if(track.isNonnull()) + { + const art::Ptr sp = trackToCRTSpacePoint.at(track.key()); + + if(sp.isNonnull()) + { + const anab::T0 spMatch = trackToCRTSpacePoint.data(track.key()).ref(); + + _tpc_has_crt_sp_match = true; + _tpc_crt_sp_score = spMatch.TriggerConfidence(); + _tpc_crt_sp_ts0 = sp->Ts0(); + _tpc_crt_sp_ts0_rwm_ref = _tpc_crt_sp_ts0 + _rwm_etrig_diff; + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref = _tpc_crt_sp_ts0 + _ptb_hlt_beam_gate_etrig_diff; + _tpc_crt_sp_dts0 = fSPdTs0Map[sp.key()]; + _tpc_crt_sp_ts1 = sp->Ts1(); + _tpc_crt_sp_ts1_rwm_ref = _tpc_crt_sp_ts1 + _rwm_crt_t1_reset_diff; + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref = _tpc_crt_sp_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; + _tpc_crt_sp_dts1 = fSPdTs1Map[sp.key()]; + } + } + } + } +} + +void sbnd::crt::CRTTimingAnalysis::ResetTPCVariables() { + _tpc_has_corrected_opflash = false; + _tpc_has_crt_sp_match = false; + + _tpc_opflash_t0 = std::numeric_limits::lowest(); + _tpc_opflash_nutof_light = std::numeric_limits::lowest(); + _tpc_opflash_nutof_charge = std::numeric_limits::lowest(); + _tpc_opflash_t0_corrected = std::numeric_limits::lowest(); + _tpc_opflash_interaction_time_rwm = std::numeric_limits::lowest(); + _tpc_opflash_front_face_rwm = std::numeric_limits::lowest(); + _tpc_crt_sp_score = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0 = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_rwm_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_dts0 = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1 = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_rwm_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_dts1 = std::numeric_limits::lowest(); } DEFINE_ART_MODULE(sbnd::crt::CRTTimingAnalysis) From 5e7f17d22faf8bfb328994a5c9455a2d12b1f487 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Wed, 25 Feb 2026 09:22:20 -0600 Subject: [PATCH 59/75] Add more reference shifts --- .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 193 +++++++++++++----- 1 file changed, 143 insertions(+), 50 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index bc2795de2..a1728c95d 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -144,14 +144,19 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { double _sp_x; double _sp_y; double _sp_z; + double _sp_front_face_adjustment; double _sp_pe; double _sp_ts0; double _sp_ts0_rwm_ref; double _sp_ts0_ptb_hlt_beam_gate_ref; + double _sp_ts0_rwm_ref_front_face; + double _sp_ts0_ptb_hlt_beam_gate_ref_front_face; double _sp_dts0; double _sp_ts1; double _sp_ts1_rwm_ref; double _sp_ts1_ptb_hlt_beam_gate_ref; + double _sp_ts1_rwm_ref_front_face; + double _sp_ts1_ptb_hlt_beam_gate_ref_front_face; double _sp_dts1; bool _sp_single_timing_chain; int16_t _sp_timing_chain; @@ -215,14 +220,26 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { double _tpc_opflash_interaction_time_rwm; double _tpc_opflash_front_face_rwm; double _tpc_crt_sp_score; + double _tpc_crt_sp_front_face_adjustment; + double _tpc_crt_sp_interaction_time_adjustment; double _tpc_crt_sp_ts0; double _tpc_crt_sp_ts0_rwm_ref; double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref; + double _tpc_crt_sp_ts0_rwm_ref_front_face; + double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face; + double _tpc_crt_sp_ts0_rwm_ref_interaction_time; + double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time; double _tpc_crt_sp_dts0; double _tpc_crt_sp_ts1; double _tpc_crt_sp_ts1_rwm_ref; double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref; + double _tpc_crt_sp_ts1_rwm_ref_front_face; + double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face; + double _tpc_crt_sp_ts1_rwm_ref_interaction_time; + double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time; double _tpc_crt_sp_dts1; + double _tpc_crt_ts0_pmt_diff; + double _tpc_crt_ts1_pmt_diff; // Maps std::map fSPTaggerMap; @@ -273,14 +290,19 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fSPTree->Branch("sp_x", &_sp_x); fSPTree->Branch("sp_y", &_sp_y); fSPTree->Branch("sp_z", &_sp_z); + fSPTree->Branch("sp_front_face_adjustment", &_sp_front_face_adjustment); fSPTree->Branch("sp_pe", &_sp_pe); fSPTree->Branch("sp_ts0", &_sp_ts0); fSPTree->Branch("sp_ts0_rwm_ref", &_sp_ts0_rwm_ref); fSPTree->Branch("sp_ts0_ptb_hlt_beam_gate_ref", &_sp_ts0_ptb_hlt_beam_gate_ref); + fSPTree->Branch("sp_ts0_rwm_ref_front_face", &_sp_ts0_rwm_ref_front_face); + fSPTree->Branch("sp_ts0_ptb_hlt_beam_gate_ref_front_face", &_sp_ts0_ptb_hlt_beam_gate_ref_front_face); fSPTree->Branch("sp_dts0", &_sp_dts0); fSPTree->Branch("sp_ts1", &_sp_ts1); fSPTree->Branch("sp_ts1_rwm_ref", &_sp_ts1_rwm_ref); fSPTree->Branch("sp_ts1_ptb_hlt_beam_gate_ref", &_sp_ts1_ptb_hlt_beam_gate_ref); + fSPTree->Branch("sp_ts1_rwm_ref_front_face", &_sp_ts1_rwm_ref_front_face); + fSPTree->Branch("sp_ts1_ptb_hlt_beam_gate_ref_front_face", &_sp_ts1_ptb_hlt_beam_gate_ref_front_face); fSPTree->Branch("sp_dts1", &_sp_dts1); fSPTree->Branch("sp_single_timing_chain", &_sp_single_timing_chain); fSPTree->Branch("sp_timing_chain", &_sp_timing_chain); @@ -378,14 +400,26 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fTPCTree->Branch("tpc_opflash_interaction_time_rwm", &_tpc_opflash_interaction_time_rwm); fTPCTree->Branch("tpc_opflash_front_face_rwm", &_tpc_opflash_front_face_rwm); fTPCTree->Branch("tpc_crt_sp_score", &_tpc_crt_sp_score); + fTPCTree->Branch("tpc_crt_sp_front_face_adjustment", &_tpc_crt_sp_front_face_adjustment); + fTPCTree->Branch("tpc_crt_sp_interaction_time_adjustment", &_tpc_crt_sp_interaction_time_adjustment); fTPCTree->Branch("tpc_crt_sp_ts0", &_tpc_crt_sp_ts0); fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref", &_tpc_crt_sp_ts0_rwm_ref); fTPCTree->Branch("tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref", &_tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref); + fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref_front_face", &_tpc_crt_sp_ts0_rwm_ref_front_face); + fTPCTree->Branch("tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face", &_tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face); + fTPCTree->Branch("tpc_crt_sp_ts0_rwm_ref_interaction_time", &_tpc_crt_sp_ts0_rwm_ref_interaction_time); + fTPCTree->Branch("tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time", &_tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time); fTPCTree->Branch("tpc_crt_sp_dts0", &_tpc_crt_sp_dts0); fTPCTree->Branch("tpc_crt_sp_ts1", &_tpc_crt_sp_ts1); fTPCTree->Branch("tpc_crt_sp_ts1_rwm_ref", &_tpc_crt_sp_ts1_rwm_ref); fTPCTree->Branch("tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref", &_tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref); + fTPCTree->Branch("tpc_crt_sp_ts1_rwm_ref_front_face", &_tpc_crt_sp_ts1_rwm_ref_front_face); + fTPCTree->Branch("tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face", &_tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face); + fTPCTree->Branch("tpc_crt_sp_ts1_rwm_ref_interaction_time", &_tpc_crt_sp_ts1_rwm_ref_interaction_time); + fTPCTree->Branch("tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time", &_tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time); fTPCTree->Branch("tpc_crt_sp_dts1", &_tpc_crt_sp_dts1); + fTPCTree->Branch("tpc_crt_ts0_pmt_diff", &_tpc_crt_ts0_pmt_diff); + fTPCTree->Branch("tpc_crt_ts1_pmt_diff", &_tpc_crt_ts1_pmt_diff); } void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) @@ -700,18 +734,23 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vectorNHits(); - _sp_tagger = cl->Tagger(); - _sp_x = sp->X(); - _sp_y = sp->Y(); - _sp_z = sp->Z(); - _sp_pe = sp->PE(); - _sp_ts0 = sp->Ts0(); - _sp_ts0_rwm_ref = _sp_ts0 + _rwm_etrig_diff; - _sp_ts0_ptb_hlt_beam_gate_ref = _sp_ts0 + _ptb_hlt_beam_gate_etrig_diff; - _sp_ts1 = sp->Ts1(); - _sp_ts1_rwm_ref = _sp_ts1 + _rwm_crt_t1_reset_diff; - _sp_ts1_ptb_hlt_beam_gate_ref = _sp_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; + _sp_nhits = cl->NHits(); + _sp_tagger = cl->Tagger(); + _sp_x = sp->X(); + _sp_y = sp->Y(); + _sp_z = sp->Z(); + _sp_front_face_adjustment = _sp_z * fSpeedOfLightNanosecondPerCentimeter; + _sp_pe = sp->PE(); + _sp_ts0 = sp->Ts0(); + _sp_ts0_rwm_ref = _sp_ts0 + _rwm_etrig_diff; + _sp_ts0_ptb_hlt_beam_gate_ref = _sp_ts0 + _ptb_hlt_beam_gate_etrig_diff; + _sp_ts0_rwm_ref_front_face = _sp_ts0_rwm_ref - _sp_front_face_adjustment; + _sp_ts0_ptb_hlt_beam_gate_ref_front_face = _sp_ts0_ptb_hlt_beam_gate_ref - _sp_front_face_adjustment; + _sp_ts1 = sp->Ts1(); + _sp_ts1_rwm_ref = _sp_ts1 + _rwm_crt_t1_reset_diff; + _sp_ts1_ptb_hlt_beam_gate_ref = _sp_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; + _sp_ts1_rwm_ref_front_face = _sp_ts1_rwm_ref - _sp_front_face_adjustment; + _sp_ts1_ptb_hlt_beam_gate_ref_front_face = _sp_ts1_ptb_hlt_beam_gate_ref - _sp_front_face_adjustment; for(unsigned i = 0; i < n_shs; ++i) { @@ -753,18 +792,23 @@ void sbnd::crt::CRTTimingAnalysis::ResetSPVariables() _sp_tagger = std::numeric_limits::lowest(); _sp_timing_chain = std::numeric_limits::lowest(); - _sp_x = std::numeric_limits::lowest(); - _sp_y = std::numeric_limits::lowest(); - _sp_z = std::numeric_limits::lowest(); - _sp_pe = std::numeric_limits::lowest(); - _sp_ts0 = std::numeric_limits::lowest(); - _sp_ts0_rwm_ref = std::numeric_limits::lowest(); - _sp_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); - _sp_dts0 = std::numeric_limits::lowest(); - _sp_ts1 = std::numeric_limits::lowest(); - _sp_ts1_rwm_ref = std::numeric_limits::lowest(); - _sp_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); - _sp_dts1 = std::numeric_limits::lowest(); + _sp_x = std::numeric_limits::lowest(); + _sp_y = std::numeric_limits::lowest(); + _sp_z = std::numeric_limits::lowest(); + _sp_front_face_adjustment = std::numeric_limits::lowest(); + _sp_pe = std::numeric_limits::lowest(); + _sp_ts0 = std::numeric_limits::lowest(); + _sp_ts0_rwm_ref = std::numeric_limits::lowest(); + _sp_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _sp_ts0_rwm_ref_front_face = std::numeric_limits::lowest(); + _sp_ts0_ptb_hlt_beam_gate_ref_front_face = std::numeric_limits::lowest(); + _sp_dts0 = std::numeric_limits::lowest(); + _sp_ts1 = std::numeric_limits::lowest(); + _sp_ts1_rwm_ref = std::numeric_limits::lowest(); + _sp_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _sp_ts1_rwm_ref_front_face = std::numeric_limits::lowest(); + _sp_ts1_ptb_hlt_beam_gate_ref_front_face = std::numeric_limits::lowest(); + _sp_dts1 = std::numeric_limits::lowest(); _sp_single_timing_chain = false; @@ -962,6 +1006,8 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vector copflash = sliceToCorrectedOpFlash.at(sl.key()); if(copflash.isNonnull()) @@ -971,7 +1017,7 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vectorNuToFLight * fMicrosecondToNanosecond; _tpc_opflash_nutof_charge = copflash->NuToFCharge * fMicrosecondToNanosecond; _tpc_opflash_t0_corrected = copflash->OpFlashT0Corrected * fMicrosecondToNanosecond; - _tpc_opflash_interaction_time_rwm = _tpc_opflash_t0_corrected + 1738.; + _tpc_opflash_interaction_time_rwm = _tpc_opflash_t0_corrected; _tpc_opflash_front_face_rwm = _tpc_opflash_interaction_time_rwm - _tpc_opflash_nutof_charge; } @@ -989,19 +1035,54 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vectorTs0(); - _tpc_crt_sp_ts0_rwm_ref = _tpc_crt_sp_ts0 + _rwm_etrig_diff; - _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref = _tpc_crt_sp_ts0 + _ptb_hlt_beam_gate_etrig_diff; - _tpc_crt_sp_dts0 = fSPdTs0Map[sp.key()]; - _tpc_crt_sp_ts1 = sp->Ts1(); - _tpc_crt_sp_ts1_rwm_ref = _tpc_crt_sp_ts1 + _rwm_crt_t1_reset_diff; - _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref = _tpc_crt_sp_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; - _tpc_crt_sp_dts1 = fSPdTs1Map[sp.key()]; + const geo::Point_t track_start = track->Start(); + const geo::Point_t track_end = track->End(); + const geo::Point_t sp_pos = sp->Pos(); + + geo::Point_t interaction_point = (track_start - sp_pos).R() > (track_end - sp_pos).R() ? track_start : track_end; + const double dist = (interaction_point - sp_pos).R(); + + if(_tpc_has_crt_sp_match) + { + const double diff = _tpc_crt_sp_ts0_rwm_ref_interaction_time - _tpc_opflash_interaction_time_rwm - 120; + const double new_crt = sp->Ts0() + _rwm_etrig_diff - dist * fSpeedOfLightNanosecondPerCentimeter; + const double new_diff = new_crt - _tpc_opflash_interaction_time_rwm - 120; + + if(new_diff > diff) + continue; + } + + _tpc_has_crt_sp_match = true; + _tpc_crt_sp_score = spMatch.TriggerConfidence(); + _tpc_crt_sp_front_face_adjustment = sp_pos.Z() * fSpeedOfLightNanosecondPerCentimeter; + _tpc_crt_sp_interaction_time_adjustment = dist * fSpeedOfLightNanosecondPerCentimeter; + _tpc_crt_sp_ts0 = sp->Ts0(); + _tpc_crt_sp_ts0_rwm_ref = _tpc_crt_sp_ts0 + _rwm_etrig_diff; + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref = _tpc_crt_sp_ts0 + _ptb_hlt_beam_gate_etrig_diff; + _tpc_crt_sp_ts0_rwm_ref_front_face = _tpc_crt_sp_ts0_rwm_ref - _tpc_crt_sp_front_face_adjustment; + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face = _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref - _tpc_crt_sp_front_face_adjustment; + _tpc_crt_sp_ts0_rwm_ref_interaction_time = _tpc_crt_sp_ts0_rwm_ref - _tpc_crt_sp_interaction_time_adjustment; + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time = _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref - _tpc_crt_sp_interaction_time_adjustment; + _tpc_crt_sp_dts0 = fSPdTs0Map[sp.key()]; + _tpc_crt_sp_ts1 = sp->Ts1(); + _tpc_crt_sp_ts1_rwm_ref = _tpc_crt_sp_ts1 + _rwm_crt_t1_reset_diff; + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref = _tpc_crt_sp_ts1 + _ptb_hlt_beam_gate_crt_t1_reset_diff; + _tpc_crt_sp_ts1_rwm_ref_front_face = _tpc_crt_sp_ts1_rwm_ref - _tpc_crt_sp_front_face_adjustment; + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face = _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref - _tpc_crt_sp_front_face_adjustment; + _tpc_crt_sp_ts1_rwm_ref_interaction_time = _tpc_crt_sp_ts1_rwm_ref - _tpc_crt_sp_interaction_time_adjustment; + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time = _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref - _tpc_crt_sp_interaction_time_adjustment; + _tpc_crt_sp_dts1 = fSPdTs1Map[sp.key()]; } } } + + if(_tpc_has_corrected_opflash && _tpc_has_crt_sp_match) + { + _tpc_crt_ts0_pmt_diff = _tpc_crt_sp_ts0_rwm_ref_interaction_time - _tpc_opflash_interaction_time_rwm; + _tpc_crt_ts1_pmt_diff = _tpc_crt_sp_ts1_rwm_ref_interaction_time - _tpc_opflash_interaction_time_rwm; + } + + fTPCTree->Fill(); } } @@ -1010,21 +1091,33 @@ void sbnd::crt::CRTTimingAnalysis::ResetTPCVariables() _tpc_has_corrected_opflash = false; _tpc_has_crt_sp_match = false; - _tpc_opflash_t0 = std::numeric_limits::lowest(); - _tpc_opflash_nutof_light = std::numeric_limits::lowest(); - _tpc_opflash_nutof_charge = std::numeric_limits::lowest(); - _tpc_opflash_t0_corrected = std::numeric_limits::lowest(); - _tpc_opflash_interaction_time_rwm = std::numeric_limits::lowest(); - _tpc_opflash_front_face_rwm = std::numeric_limits::lowest(); - _tpc_crt_sp_score = std::numeric_limits::lowest(); - _tpc_crt_sp_ts0 = std::numeric_limits::lowest(); - _tpc_crt_sp_ts0_rwm_ref = std::numeric_limits::lowest(); - _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); - _tpc_crt_sp_dts0 = std::numeric_limits::lowest(); - _tpc_crt_sp_ts1 = std::numeric_limits::lowest(); - _tpc_crt_sp_ts1_rwm_ref = std::numeric_limits::lowest(); - _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); - _tpc_crt_sp_dts1 = std::numeric_limits::lowest(); + _tpc_opflash_t0 = std::numeric_limits::lowest(); + _tpc_opflash_nutof_light = std::numeric_limits::lowest(); + _tpc_opflash_nutof_charge = std::numeric_limits::lowest(); + _tpc_opflash_t0_corrected = std::numeric_limits::lowest(); + _tpc_opflash_interaction_time_rwm = std::numeric_limits::lowest(); + _tpc_opflash_front_face_rwm = std::numeric_limits::lowest(); + _tpc_crt_sp_score = std::numeric_limits::lowest(); + _tpc_crt_sp_front_face_adjustment = std::numeric_limits::lowest(); + _tpc_crt_sp_interaction_time_adjustment = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0 = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_rwm_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_rwm_ref_front_face = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_rwm_ref_interaction_time = std::numeric_limits::lowest(); + _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time = std::numeric_limits::lowest(); + _tpc_crt_sp_dts0 = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1 = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_rwm_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_rwm_ref_front_face = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_rwm_ref_interaction_time = std::numeric_limits::lowest(); + _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time = std::numeric_limits::lowest(); + _tpc_crt_sp_dts1 = std::numeric_limits::lowest(); + _tpc_crt_ts0_pmt_diff = std::numeric_limits::lowest(); + _tpc_crt_ts1_pmt_diff = std::numeric_limits::lowest(); } DEFINE_ART_MODULE(sbnd::crt::CRTTimingAnalysis) From 2b8362d60f3ee34413cfe927727b109e4bbc6651 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 26 Feb 2026 04:02:08 -0600 Subject: [PATCH 60/75] Add a few missing branches --- .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 179 ++++++++++-------- 1 file changed, 105 insertions(+), 74 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index a1728c95d..a1bdf11bb 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -172,80 +172,87 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { std::vector _sp_sh_cable_length_ts1_set; std::vector _sp_sh_calib_offset_ts1_set; - double _tr_start_x; - double _tr_start_y; - double _tr_start_z; - double _tr_end_x; - double _tr_end_y; - double _tr_end_z; - double _tr_dir_x; - double _tr_dir_y; - double _tr_dir_z; - double _tr_ts0; - double _tr_ts0_rwm_ref; - double _tr_ts0_ptb_hlt_beam_gate_ref; - double _tr_ts1; - double _tr_ts1_rwm_ref; - double _tr_ts1_ptb_hlt_beam_gate_ref; - double _tr_pe; - double _tr_length; - double _tr_length_tof; - double _tr_tof_ts0; - double _tr_tof_diff_ts0; - double _tr_tof_ts1; - double _tr_tof_diff_ts1; - double _tr_theta; - double _tr_phi; - bool _tr_triple; - int16_t _tr_tagger1; - int16_t _tr_tagger2; - int16_t _tr_tagger3; - int16_t _tr_start_tagger; - double _tr_start_dts0; - double _tr_start_dts1; - bool _tr_start_single_timing_chain; - int16_t _tr_start_timing_chain; - int16_t _tr_end_tagger; - double _tr_end_dts0; - double _tr_end_dts1; - bool _tr_end_single_timing_chain; - int16_t _tr_end_timing_chain; - - bool _tpc_has_corrected_opflash; - bool _tpc_has_crt_sp_match; - double _tpc_opflash_t0; - double _tpc_opflash_nutof_light; - double _tpc_opflash_nutof_charge; - double _tpc_opflash_t0_corrected; - double _tpc_opflash_interaction_time_rwm; - double _tpc_opflash_front_face_rwm; - double _tpc_crt_sp_score; - double _tpc_crt_sp_front_face_adjustment; - double _tpc_crt_sp_interaction_time_adjustment; - double _tpc_crt_sp_ts0; - double _tpc_crt_sp_ts0_rwm_ref; - double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref; - double _tpc_crt_sp_ts0_rwm_ref_front_face; - double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face; - double _tpc_crt_sp_ts0_rwm_ref_interaction_time; - double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time; - double _tpc_crt_sp_dts0; - double _tpc_crt_sp_ts1; - double _tpc_crt_sp_ts1_rwm_ref; - double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref; - double _tpc_crt_sp_ts1_rwm_ref_front_face; - double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face; - double _tpc_crt_sp_ts1_rwm_ref_interaction_time; - double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time; - double _tpc_crt_sp_dts1; - double _tpc_crt_ts0_pmt_diff; - double _tpc_crt_ts1_pmt_diff; + double _tr_start_x; + double _tr_start_y; + double _tr_start_z; + double _tr_end_x; + double _tr_end_y; + double _tr_end_z; + double _tr_dir_x; + double _tr_dir_y; + double _tr_dir_z; + double _tr_ts0; + double _tr_ts0_rwm_ref; + double _tr_ts0_ptb_hlt_beam_gate_ref; + double _tr_ts1; + double _tr_ts1_rwm_ref; + double _tr_ts1_ptb_hlt_beam_gate_ref; + double _tr_pe; + double _tr_length; + double _tr_length_tof; + double _tr_tof_ts0; + double _tr_tof_diff_ts0; + double _tr_tof_ts1; + double _tr_tof_diff_ts1; + double _tr_theta; + double _tr_phi; + bool _tr_triple; + int16_t _tr_tagger1; + int16_t _tr_tagger2; + int16_t _tr_tagger3; + int16_t _tr_start_tagger; + uint16_t _tr_start_nhits; + double _tr_start_dts0; + double _tr_start_dts1; + bool _tr_start_single_timing_chain; + int16_t _tr_start_timing_chain; + int16_t _tr_end_tagger; + uint16_t _tr_end_nhits; + double _tr_end_dts0; + double _tr_end_dts1; + bool _tr_end_single_timing_chain; + int16_t _tr_end_timing_chain; + + bool _tpc_has_corrected_opflash; + bool _tpc_has_crt_sp_match; + double _tpc_opflash_t0; + double _tpc_opflash_nutof_light; + double _tpc_opflash_nutof_charge; + double _tpc_opflash_t0_corrected; + double _tpc_opflash_interaction_time_rwm; + double _tpc_opflash_front_face_rwm; + double _tpc_crt_sp_score; + int16_t _tpc_crt_sp_tagger; + uint16_t _tpc_crt_sp_nhits; + bool _tpc_crt_sp_single_timing_chain; + int16_t _tpc_crt_sp_timing_chain; + double _tpc_crt_sp_front_face_adjustment; + double _tpc_crt_sp_interaction_time_adjustment; + double _tpc_crt_sp_ts0; + double _tpc_crt_sp_ts0_rwm_ref; + double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref; + double _tpc_crt_sp_ts0_rwm_ref_front_face; + double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_front_face; + double _tpc_crt_sp_ts0_rwm_ref_interaction_time; + double _tpc_crt_sp_ts0_ptb_hlt_beam_gate_ref_interaction_time; + double _tpc_crt_sp_dts0; + double _tpc_crt_sp_ts1; + double _tpc_crt_sp_ts1_rwm_ref; + double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref; + double _tpc_crt_sp_ts1_rwm_ref_front_face; + double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_front_face; + double _tpc_crt_sp_ts1_rwm_ref_interaction_time; + double _tpc_crt_sp_ts1_ptb_hlt_beam_gate_ref_interaction_time; + double _tpc_crt_sp_dts1; + double _tpc_crt_ts0_pmt_diff; + double _tpc_crt_ts1_pmt_diff; // Maps - std::map fSPTaggerMap; - std::map fSPdTs0Map; - std::map fSPdTs1Map; - std::map fSPTimingChainMap; + std::map fSPTaggerMap; + std::map fSPNHitsMap; + std::map fSPdTs0Map; + std::map fSPdTs1Map; + std::map fSPTimingChainMap; }; sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) @@ -364,11 +371,13 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fTrTree->Branch("tr_tagger2", &_tr_tagger2); fTrTree->Branch("tr_tagger3", &_tr_tagger3); fTrTree->Branch("tr_start_tagger", &_tr_start_tagger); + fTrTree->Branch("tr_start_nhits", &_tr_start_nhits); fTrTree->Branch("tr_start_dts0", &_tr_start_dts0); fTrTree->Branch("tr_start_dts1", &_tr_start_dts1); fTrTree->Branch("tr_start_single_timing_chain", &_tr_start_single_timing_chain); fTrTree->Branch("tr_start_timing_chain", &_tr_start_timing_chain); fTrTree->Branch("tr_end_tagger", &_tr_end_tagger); + fTrTree->Branch("tr_end_nhits", &_tr_end_nhits); fTrTree->Branch("tr_end_dts0", &_tr_end_dts0); fTrTree->Branch("tr_end_dts1", &_tr_end_dts1); fTrTree->Branch("tr_end_single_timing_chain", &_tr_end_single_timing_chain); @@ -400,6 +409,10 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fTPCTree->Branch("tpc_opflash_interaction_time_rwm", &_tpc_opflash_interaction_time_rwm); fTPCTree->Branch("tpc_opflash_front_face_rwm", &_tpc_opflash_front_face_rwm); fTPCTree->Branch("tpc_crt_sp_score", &_tpc_crt_sp_score); + fTPCTree->Branch("tpc_crt_sp_tagger", &_tpc_crt_sp_tagger); + fTPCTree->Branch("tpc_crt_sp_nhits", &_tpc_crt_sp_nhits); + fTPCTree->Branch("tpc_crt_sp_single_timing_chain", &_tpc_crt_sp_single_timing_chain); + fTPCTree->Branch("tpc_crt_sp_timing_chain", &_tpc_crt_sp_timing_chain); fTPCTree->Branch("tpc_crt_sp_front_face_adjustment", &_tpc_crt_sp_front_face_adjustment); fTPCTree->Branch("tpc_crt_sp_interaction_time_adjustment", &_tpc_crt_sp_interaction_time_adjustment); fTPCTree->Branch("tpc_crt_sp_ts0", &_tpc_crt_sp_ts0); @@ -556,6 +569,7 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) void sbnd::crt::CRTTimingAnalysis::ResetMaps() { fSPTaggerMap.clear(); + fSPNHitsMap.clear(); fSPdTs0Map.clear(); fSPdTs1Map.clear(); fSPTimingChainMap.clear(); @@ -779,6 +793,7 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vectorFill(); fSPTaggerMap[sp.key()] = _sp_tagger; + fSPNHitsMap[sp.key()] = _sp_nhits; fSPdTs0Map[sp.key()] = _sp_dts0; fSPdTs1Map[sp.key()] = _sp_dts1; fSPTimingChainMap[sp.key()] = _sp_timing_chain; @@ -925,11 +940,13 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTTracks(const std::vectorTs1() - start->Ts1(); _tr_tof_diff_ts1 = _tr_tof_ts1 - _tr_length_tof; _tr_start_tagger = fSPTaggerMap[start.key()]; + _tr_start_nhits = fSPNHitsMap[start.key()]; _tr_start_dts0 = fSPdTs0Map[start.key()]; _tr_start_dts1 = fSPdTs1Map[start.key()]; _tr_start_timing_chain = fSPTimingChainMap[start.key()]; _tr_start_single_timing_chain = _tr_start_timing_chain != -1; _tr_end_tagger = fSPTaggerMap[end.key()]; + _tr_end_nhits = fSPNHitsMap[start.key()]; _tr_end_dts0 = fSPdTs0Map[end.key()]; _tr_end_dts1 = fSPdTs1Map[end.key()]; _tr_end_timing_chain = fSPTimingChainMap[end.key()]; @@ -996,6 +1013,10 @@ void sbnd::crt::CRTTimingAnalysis::ResetTrVariables() _tr_start_timing_chain = std::numeric_limits::lowest(); _tr_end_tagger = std::numeric_limits::lowest(); _tr_end_timing_chain = std::numeric_limits::lowest(); + + _tr_start_nhits = std::numeric_limits::lowest(); + _tr_end_nhits = std::numeric_limits::lowest(); + } void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vector> &TPCSliceVec, @@ -1054,6 +1075,10 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vectorTs0(); @@ -1088,8 +1113,9 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseTPCSlices(const std::vector::lowest(); _tpc_opflash_nutof_light = std::numeric_limits::lowest(); @@ -1118,6 +1144,11 @@ void sbnd::crt::CRTTimingAnalysis::ResetTPCVariables() _tpc_crt_sp_dts1 = std::numeric_limits::lowest(); _tpc_crt_ts0_pmt_diff = std::numeric_limits::lowest(); _tpc_crt_ts1_pmt_diff = std::numeric_limits::lowest(); + + _tpc_crt_sp_tagger = std::numeric_limits::lowest(); + _tpc_crt_sp_timing_chain = std::numeric_limits::lowest(); + + _tpc_crt_sp_nhits = std::numeric_limits::lowest(); } DEFINE_ART_MODULE(sbnd::crt::CRTTimingAnalysis) From 7bc5dee871c6b1ea1dc6a4689cc405e50bdb2439 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 26 Feb 2026 04:11:49 -0600 Subject: [PATCH 61/75] More sensible default for uint --- sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index a1bdf11bb..73846af9c 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -1014,8 +1014,8 @@ void sbnd::crt::CRTTimingAnalysis::ResetTrVariables() _tr_end_tagger = std::numeric_limits::lowest(); _tr_end_timing_chain = std::numeric_limits::lowest(); - _tr_start_nhits = std::numeric_limits::lowest(); - _tr_end_nhits = std::numeric_limits::lowest(); + _tr_start_nhits = std::numeric_limits::max(); + _tr_end_nhits = std::numeric_limits::max(); } @@ -1148,7 +1148,7 @@ void sbnd::crt::CRTTimingAnalysis::ResetTPCVariables() _tpc_crt_sp_tagger = std::numeric_limits::lowest(); _tpc_crt_sp_timing_chain = std::numeric_limits::lowest(); - _tpc_crt_sp_nhits = std::numeric_limits::lowest(); + _tpc_crt_sp_nhits = std::numeric_limits::max(); } DEFINE_ART_MODULE(sbnd::crt::CRTTimingAnalysis) From 44a0672f903903af59406a8ebc4be3f14abd71af Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Fri, 27 Feb 2026 04:54:01 -0600 Subject: [PATCH 62/75] Remove unnecessary tophat analysis module --- .../CRT/CRTAna/CRTTopHatAnalysis_module.cc | 821 ------------------ sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl | 12 - sbndcode/CRT/CRTAna/run_crttophatana_data.fcl | 28 - 3 files changed, 861 deletions(-) delete mode 100644 sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc delete mode 100644 sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl delete mode 100644 sbndcode/CRT/CRTAna/run_crttophatana_data.fcl diff --git a/sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc deleted file mode 100644 index f338ce846..000000000 --- a/sbndcode/CRT/CRTAna/CRTTopHatAnalysis_module.cc +++ /dev/null @@ -1,821 +0,0 @@ -//////////////////////////////////////////////////////////////////////// -// Class: CRTTopHatAnalysis -// Plugin Type: analyzer -// File: CRTTopHatAnalysis_module.cc -// Author: Henry Lay (h.lay@sheffield.ac.uk) -//////////////////////////////////////////////////////////////////////// - -#include "art/Framework/Core/EDAnalyzer.h" -#include "art/Framework/Core/ModuleMacros.h" -#include "art/Framework/Principal/Event.h" -#include "art/Framework/Principal/Handle.h" -#include "art/Framework/Principal/Run.h" -#include "art/Framework/Principal/SubRun.h" -#include "canvas/Utilities/InputTag.h" -#include "fhiclcpp/ParameterSet.h" -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "art_root_io/TFileService.h" -#include "canvas/Persistency/Common/FindManyP.h" - -#include "TTree.h" - -#include "lardataobj/AnalysisBase/T0.h" -#include "lardataobj/RecoBase/Track.h" -#include "lardataobj/RecoBase/PFParticle.h" -#include "lardataobj/RecoBase/PFParticleMetadata.h" - -#include "larsim/Utils/TruthMatchUtils.h" -#include "lardata/DetectorInfoServices/DetectorClocksService.h" - -#include "sbndaq-artdaq-core/Obj/SBND/pmtSoftwareTrigger.hh" - -#include "sbnobj/SBND/CRT/FEBData.hh" -#include "sbnobj/SBND/CRT/CRTStripHit.hh" -#include "sbnobj/SBND/CRT/CRTCluster.hh" -#include "sbnobj/SBND/CRT/CRTSpacePoint.hh" -#include "sbnobj/SBND/CRT/CRTTrack.hh" -#include "sbnobj/SBND/Timing/DAQTimestamp.hh" - -#include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" -#include "sbndcode/Geometry/GeometryWrappers/TPCGeoAlg.h" -#include "sbndcode/CRT/CRTBackTracker/CRTBackTrackerAlg.h" -#include "sbndcode/CRT/CRTUtils/CRTCommonUtils.h" -#include "sbndcode/Decoders/PTB/sbndptb.h" -#include "sbndcode/Timing/SBNDRawTimingObj.h" - -namespace sbnd::crt { - class CRTTopHatAnalysis; -} - -class sbnd::crt::CRTTopHatAnalysis : public art::EDAnalyzer { -public: - explicit CRTTopHatAnalysis(fhicl::ParameterSet const& p); - // The compiler-generated destructor is fine for non-base - // classes without bare pointers or other resource use. - - // Plugins should not be copied or assigned. - CRTTopHatAnalysis(CRTTopHatAnalysis const&) = delete; - CRTTopHatAnalysis(CRTTopHatAnalysis&&) = delete; - CRTTopHatAnalysis& operator=(CRTTopHatAnalysis const&) = delete; - CRTTopHatAnalysis& operator=(CRTTopHatAnalysis&&) = delete; - - // Required functions. - void analyze(art::Event const& e) override; - - void AnalysePTBs(std::vector> &PTBVec); - - void AnalyseTDCs(std::vector> &TDCVec); - - void SortReferencing(); - - void AnalyseCRTStripHits(const art::Event &e, const std::vector> &CRTStripHitVec); - - void AnalyseCRTClusters(const art::Event &e, const std::vector> &CRTClusterVec, - const art::FindManyP &clustersToSpacePoints); - - void AnalyseCRTTracks(const art::Event &e, const std::vector> &CRTTrackVec); - - void AnalysePMTSoftwareTriggers(const art::Event &e, const std::vector> &PMTSoftwareTriggerVec); - - -private: - - art::ServiceHandle fCRTGeoService; - TPCGeoAlg fTPCGeoAlg; - - std::string fCRTStripHitModuleLabel, fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, - fCRTTrackModuleLabel, fPTBModuleLabel, fTDCModuleLabel, fTimingReferenceModuleLabel, - fPMTSoftwareTriggerModuleLabel; - bool fDebug, fCutT0, fSavePMTSoftwareTrigger; - double fMinT0, fMaxT0; - std::vector fAllowedPTBHLTs; - - TTree* fTree; - - // Tree variables - - int _run; - int _subrun; - int _event; - int _crt_timing_reference_type; - int _crt_timing_reference_channel; - - //strip hit to select the strip which has ADC above threshold - std::vector _sh_channel; - std::vector _sh_tagger; - std::vector _sh_ts0; - std::vector _sh_ts0_rwm_ref; - std::vector _sh_ts0_ptb_hlt_beam_gate_ref; - std::vector _sh_ts1; - std::vector _sh_ts1_rwm_ref; - std::vector _sh_ts1_ptb_hlt_beam_gate_ref; - std::vector _sh_unixs; - std::vector _sh_pos; - std::vector _sh_err; - std::vector _sh_adc1; - std::vector _sh_adc2; - std::vector _sh_saturated1; - std::vector _sh_saturated2; - std::vector _sh_truth_trackid; - std::vector _sh_truth_completeness; - std::vector _sh_truth_purity; - std::vector _sh_truth_pos; - std::vector _sh_truth_energy; - std::vector _sh_truth_time; - - //cluster from x-y coincidence for CRTSpacePoint - std::vector _cl_ts0; - std::vector _cl_ts0_rwm_ref; - std::vector _cl_ts0_ptb_hlt_beam_gate_ref; - std::vector _cl_ts1; - std::vector _cl_ts1_rwm_ref; - std::vector _cl_ts1_ptb_hlt_beam_gate_ref; - std::vector _cl_unixs; - std::vector _cl_nhits; - std::vector _cl_tagger; - std::vector _cl_composition; - std::vector _cl_has_sp; - std::vector _cl_sp_x; - std::vector _cl_sp_ex; - std::vector _cl_sp_y; - std::vector _cl_sp_ey; - std::vector _cl_sp_z; - std::vector _cl_sp_ez; - std::vector _cl_sp_pe; - std::vector _cl_sp_ts0; - std::vector _cl_sp_ts0_rwm_ref; - std::vector _cl_sp_ts0_ptb_hlt_beam_gate_ref; - std::vector _cl_sp_ets0; - std::vector _cl_sp_ts1; - std::vector _cl_sp_ts1_rwm_ref; - std::vector _cl_sp_ts1_ptb_hlt_beam_gate_ref; - std::vector _cl_sp_ets1; - std::vector _cl_sp_complete; - - //track level information - std::vector _tr_start_x; - std::vector _tr_start_y; - std::vector _tr_start_z; - std::vector _tr_end_x; - std::vector _tr_end_y; - std::vector _tr_end_z; - std::vector _tr_dir_x; - std::vector _tr_dir_y; - std::vector _tr_dir_z; - std::vector _tr_ts0; - std::vector _tr_ts0_rwm_ref; - std::vector _tr_ts0_ptb_hlt_beam_gate_ref; - std::vector _tr_ets0; - std::vector _tr_ts1; - std::vector _tr_ts1_rwm_ref; - std::vector _tr_ts1_ptb_hlt_beam_gate_ref; - std::vector _tr_ets1; - std::vector _tr_pe; - std::vector _tr_length; - std::vector _tr_tof; - std::vector _tr_theta; - std::vector _tr_phi; - std::vector _tr_triple; - std::vector _tr_tagger1; - std::vector _tr_tagger2; - std::vector _tr_tagger3; - - std::vector _ptb_hlt_trigger; - std::vector _ptb_hlt_timestamp; - - std::vector _ptb_llt_trigger; - std::vector _ptb_llt_timestamp; - - std::vector _tdc_channel; - std::vector _tdc_timestamp; - std::vector _tdc_offset; - std::vector _tdc_name; - - bool _etrig_good, _rwm_good, _ptb_hlt_beam_gate_good, _crt_t1_reset_good; - double _rwm_etrig_diff, _ptb_hlt_beam_gate_etrig_diff, _rwm_crt_t1_reset_diff, _ptb_hlt_beam_gate_crt_t1_reset_diff, - _rwm_ptb_hlt_beam_gate_diff; - - bool _pmt_st_found_trigger; - double _pmt_st_corrected_peak_time, _pmt_st_corrected_peak_time_rwm_ref; -}; - -sbnd::crt::CRTTopHatAnalysis::CRTTopHatAnalysis(fhicl::ParameterSet const& p) - : EDAnalyzer{p} -{ - fCRTStripHitModuleLabel = p.get("CRTStripHitModuleLabel", "crtstrips"); - fCRTClusterModuleLabel = p.get("CRTClusterModuleLabel", "crtclustering"); - fCRTSpacePointModuleLabel = p.get("CRTSpacePointModuleLabel", "crtspacepoints"); - fCRTTrackModuleLabel = p.get("CRTTrackModuleLabel", "crttracks"); - fPTBModuleLabel = p.get("PTBModuleLabel", "ptbdecoder"); - fTDCModuleLabel = p.get("TDCModuleLabel", "tdcdecoder"); - fTimingReferenceModuleLabel = p.get("TimingReferenceModuleLabel", "crtstrips"); - fPMTSoftwareTriggerModuleLabel = p.get("PMTSoftwareTriggerModuleLabel", "pmtmetricbnblight"); - fDebug = p.get("Debug", false); - fCutT0 = p.get("CutT0", false); - fSavePMTSoftwareTrigger = p.get("SavePMTSoftwareTrigger", false); - fMinT0 = p.get("MinT0", std::numeric_limits::min()); - fMaxT0 = p.get("MaxT0", std::numeric_limits::max()); - fAllowedPTBHLTs = p.get>("AllowedPTBHLTs", { 26, 27 }); - - art::ServiceHandle fs; - - fTree = fs->make("tree",""); - fTree->Branch("run", &_run); - fTree->Branch("subrun", &_subrun); - fTree->Branch("event", &_event); - fTree->Branch("crt_timing_reference_type", &_crt_timing_reference_type); - fTree->Branch("crt_timing_reference_channel", &_crt_timing_reference_channel); - - fTree->Branch("sh_channel", "std::vector", &_sh_channel); - fTree->Branch("sh_tagger", "std::vector", &_sh_tagger); - fTree->Branch("sh_ts0", "std::vector", &_sh_ts0); - fTree->Branch("sh_ts0_rwm_ref", "std::vector", &_sh_ts0_rwm_ref); - fTree->Branch("sh_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_sh_ts0_ptb_hlt_beam_gate_ref); - fTree->Branch("sh_ts1", "std::vector", &_sh_ts1); - fTree->Branch("sh_ts1_rwm_ref", "std::vector", &_sh_ts1_rwm_ref); - fTree->Branch("sh_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_sh_ts1_ptb_hlt_beam_gate_ref); - fTree->Branch("sh_unixs", "std::vector", &_sh_unixs); - fTree->Branch("sh_pos", "std::vector", &_sh_pos); - fTree->Branch("sh_err", "std::vector", &_sh_err); - fTree->Branch("sh_adc1", "std::vector", &_sh_adc1); - fTree->Branch("sh_adc2", "std::vector", &_sh_adc2); - fTree->Branch("sh_saturated1", "std::vector", &_sh_saturated1); - fTree->Branch("sh_saturated2", "std::vector", &_sh_saturated2); - - fTree->Branch("cl_ts0", "std::vector", &_cl_ts0); - fTree->Branch("cl_ts0_rwm_ref", "std::vector", &_cl_ts0_rwm_ref); - fTree->Branch("cl_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_cl_ts0_ptb_hlt_beam_gate_ref); - fTree->Branch("cl_ts1", "std::vector", &_cl_ts1); - fTree->Branch("cl_ts1_rwm_ref", "std::vector", &_cl_ts1_rwm_ref); - fTree->Branch("cl_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_cl_ts1_ptb_hlt_beam_gate_ref); - fTree->Branch("cl_unixs", "std::vector", &_cl_unixs); - fTree->Branch("cl_nhits", "std::vector", &_cl_nhits); - fTree->Branch("cl_tagger", "std::vector", &_cl_tagger); - fTree->Branch("cl_composition", "std::vector", &_cl_composition); - fTree->Branch("cl_has_sp", "std::vector", &_cl_has_sp); - fTree->Branch("cl_sp_x", "std::vector", &_cl_sp_x); - fTree->Branch("cl_sp_ex", "std::vector", &_cl_sp_ex); - fTree->Branch("cl_sp_y", "std::vector", &_cl_sp_y); - fTree->Branch("cl_sp_ey", "std::vector", &_cl_sp_ey); - fTree->Branch("cl_sp_z", "std::vector", &_cl_sp_z); - fTree->Branch("cl_sp_ez", "std::vector", &_cl_sp_ez); - fTree->Branch("cl_sp_pe", "std::vector", &_cl_sp_pe); - fTree->Branch("cl_sp_ts0", "std::vector", &_cl_sp_ts0); - fTree->Branch("cl_sp_ts0_rwm_ref", "std::vector", &_cl_sp_ts0_rwm_ref); - fTree->Branch("cl_sp_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_cl_sp_ts0_ptb_hlt_beam_gate_ref); - fTree->Branch("cl_sp_ets0", "std::vector", &_cl_sp_ets0); - fTree->Branch("cl_sp_ts1", "std::vector", &_cl_sp_ts1); - fTree->Branch("cl_sp_ts1_rwm_ref", "std::vector", &_cl_sp_ts1_rwm_ref); - fTree->Branch("cl_sp_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_cl_sp_ts1_ptb_hlt_beam_gate_ref); - fTree->Branch("cl_sp_ets1", "std::vector", &_cl_sp_ets1); - fTree->Branch("cl_sp_complete", "std::vector", &_cl_sp_complete); - - fTree->Branch("tr_start_x", "std::vector", &_tr_start_x); - fTree->Branch("tr_start_y", "std::vector", &_tr_start_y); - fTree->Branch("tr_start_z", "std::vector", &_tr_start_z); - fTree->Branch("tr_end_x", "std::vector", &_tr_end_x); - fTree->Branch("tr_end_y", "std::vector", &_tr_end_y); - fTree->Branch("tr_end_z", "std::vector", &_tr_end_z); - fTree->Branch("tr_dir_x", "std::vector", &_tr_dir_x); - fTree->Branch("tr_dir_y", "std::vector", &_tr_dir_y); - fTree->Branch("tr_dir_z", "std::vector", &_tr_dir_z); - fTree->Branch("tr_ts0", "std::vector", &_tr_ts0); - fTree->Branch("tr_ts0_rwm_ref", "std::vector", &_tr_ts0_rwm_ref); - fTree->Branch("tr_ts0_ptb_hlt_beam_gate_ref", "std::vector", &_tr_ts0_ptb_hlt_beam_gate_ref); - fTree->Branch("tr_ets0", "std::vector", &_tr_ets0); - fTree->Branch("tr_ts1", "std::vector", &_tr_ts1); - fTree->Branch("tr_ts1_rwm_ref", "std::vector", &_tr_ts1_rwm_ref); - fTree->Branch("tr_ts1_ptb_hlt_beam_gate_ref", "std::vector", &_tr_ts1_ptb_hlt_beam_gate_ref); - fTree->Branch("tr_ets1", "std::vector", &_tr_ets1); - fTree->Branch("tr_pe", "std::vector", &_tr_pe); - fTree->Branch("tr_length", "std::vector", &_tr_length); - fTree->Branch("tr_tof", "std::vector", &_tr_tof); - fTree->Branch("tr_theta", "std::vector", &_tr_theta); - fTree->Branch("tr_phi", "std::vector", &_tr_phi); - fTree->Branch("tr_triple", "std::vector", &_tr_triple); - fTree->Branch("tr_tagger1", "std::vector", &_tr_tagger1); - fTree->Branch("tr_tagger2", "std::vector", &_tr_tagger2); - fTree->Branch("tr_tagger3", "std::vector", &_tr_tagger3); - - fTree->Branch("ptb_hlt_trigger", "std::vector", &_ptb_hlt_trigger); - fTree->Branch("ptb_hlt_timestamp", "std::vector", &_ptb_hlt_timestamp); - fTree->Branch("ptb_llt_trigger", "std::vector", &_ptb_llt_trigger); - fTree->Branch("ptb_llt_timestamp", "std::vector", &_ptb_llt_timestamp); - - fTree->Branch("tdc_channel", "std::vector", &_tdc_channel); - fTree->Branch("tdc_timestamp", "std::vector", &_tdc_timestamp); - fTree->Branch("tdc_offset", "std::vector", &_tdc_offset); - fTree->Branch("tdc_name", "std::vector", &_tdc_name); - - fTree->Branch("etrig_good", &_etrig_good); - fTree->Branch("rwm_good", &_rwm_good); - fTree->Branch("ptb_hlt_beam_gate_good", &_ptb_hlt_beam_gate_good); - fTree->Branch("crt_t1_reset_good", &_crt_t1_reset_good); - fTree->Branch("rwm_etrig_diff", &_rwm_etrig_diff); - fTree->Branch("ptb_hlt_beam_gate_etrig_diff", &_ptb_hlt_beam_gate_etrig_diff); - fTree->Branch("rwm_crt_t1_reset_diff", &_rwm_crt_t1_reset_diff); - fTree->Branch("ptb_hlt_beam_gate_crt_t1_reset_diff", &_ptb_hlt_beam_gate_crt_t1_reset_diff); - fTree->Branch("rwm_ptb_hlt_beam_gate_diff", &_rwm_ptb_hlt_beam_gate_diff); - - if(fSavePMTSoftwareTrigger) - { - fTree->Branch("pmt_st_found_trigger", &_pmt_st_found_trigger); - fTree->Branch("pmt_st_corrected_peak_time", &_pmt_st_corrected_peak_time); - fTree->Branch("pmt_st_corrected_peak_time", &_pmt_st_corrected_peak_time); - fTree->Branch("pmt_st_corrected_peak_time_rwm_ref", &_pmt_st_corrected_peak_time_rwm_ref); - } -} - -void sbnd::crt::CRTTopHatAnalysis::analyze(art::Event const& e) -{ - _run = e.id().run(); - _subrun = e.id().subRun(); - _event = e.id().event(); - - _crt_timing_reference_type = -1; - _crt_timing_reference_channel = -1; - - art::Handle TimingReferenceHandle; - e.getByLabel(fTimingReferenceModuleLabel, TimingReferenceHandle); - if(TimingReferenceHandle.isValid()) - { - _crt_timing_reference_type = TimingReferenceHandle->timingType; - _crt_timing_reference_channel = TimingReferenceHandle->timingChannel; - } - - // Get PTBs - art::Handle> PTBHandle; - e.getByLabel(fPTBModuleLabel, PTBHandle); - if(!PTBHandle.isValid()){ - std::cout << "PTB product " << fPTBModuleLabel << " not found..." << std::endl; - throw std::exception(); - } - std::vector> PTBVec; - art::fill_ptr_vector(PTBVec, PTBHandle); - - // Fill PTB variables - AnalysePTBs(PTBVec); - - // Get TDCs - art::Handle> TDCHandle; - e.getByLabel(fTDCModuleLabel, TDCHandle); - if(!TDCHandle.isValid()){ - std::cout << "TDC product " << fTDCModuleLabel << " not found..." << std::endl; - throw std::exception(); - } - std::vector> TDCVec; - art::fill_ptr_vector(TDCVec, TDCHandle); - - // Fill TDC variables - AnalyseTDCs(TDCVec); - - SortReferencing(); - - // Get CRTStripHits - art::Handle> CRTStripHitHandle; - e.getByLabel(fCRTStripHitModuleLabel, CRTStripHitHandle); - if(!CRTStripHitHandle.isValid()){ - std::cout << "CRTStripHit product " << fCRTStripHitModuleLabel << " not found..." << std::endl; - throw std::exception(); - } - std::vector> CRTStripHitVec; - art::fill_ptr_vector(CRTStripHitVec, CRTStripHitHandle); - - // Fill CRTStripHit variables - AnalyseCRTStripHits(e, CRTStripHitVec); - - // Get CRTClusters - art::Handle> CRTClusterHandle; - e.getByLabel(fCRTClusterModuleLabel, CRTClusterHandle); - if(!CRTClusterHandle.isValid()){ - std::cout << "CRTCluster product " << fCRTClusterModuleLabel << " not found..." << std::endl; - throw std::exception(); - } - std::vector> CRTClusterVec; - art::fill_ptr_vector(CRTClusterVec, CRTClusterHandle); - - // Get CRTCluster to CRTSpacePoint Assns - art::FindManyP clustersToSpacePoints(CRTClusterHandle, e, fCRTSpacePointModuleLabel); - - // Fill CRTCluster variables - AnalyseCRTClusters(e, CRTClusterVec, clustersToSpacePoints); - - // Get CRTTracks - art::Handle> CRTTrackHandle; - e.getByLabel(fCRTTrackModuleLabel, CRTTrackHandle); - if(!CRTTrackHandle.isValid()){ - std::cout << "CRTTrack product " << fCRTTrackModuleLabel << " not found..." << std::endl; - throw std::exception(); - } - std::vector> CRTTrackVec; - art::fill_ptr_vector(CRTTrackVec, CRTTrackHandle); - - // Fill CRTTrack variables - AnalyseCRTTracks(e, CRTTrackVec); - - if(fSavePMTSoftwareTrigger) - { - // Get PMTSoftwareTriggers - art::Handle> PMTSoftwareTriggerHandle; - e.getByLabel(fPMTSoftwareTriggerModuleLabel, PMTSoftwareTriggerHandle); - if(!PMTSoftwareTriggerHandle.isValid()){ - std::cout << "PMTSoftwareTrigger product " << fPMTSoftwareTriggerModuleLabel << " not found..." << std::endl; - throw std::exception(); - } - std::vector> PMTSoftwareTriggerVec; - art::fill_ptr_vector(PMTSoftwareTriggerVec, PMTSoftwareTriggerHandle); - - // Fill PMTSoftwareTrigger variables - AnalysePMTSoftwareTriggers(e, PMTSoftwareTriggerVec); - } - - fTree->Fill(); -} - -void sbnd::crt::CRTTopHatAnalysis::AnalysePTBs(std::vector> &PTBVec) -{ - unsigned nHLTs = 0; - - for(auto const& ptb : PTBVec) - nHLTs += ptb->GetNHLTriggers(); - - _ptb_hlt_trigger.resize(nHLTs); - _ptb_hlt_timestamp.resize(nHLTs); - - unsigned hlt_i = 0; - - for(auto const& ptb : PTBVec) - { - for(unsigned i = 0; i < ptb->GetNHLTriggers(); ++i) - { - _ptb_hlt_trigger[hlt_i] = ptb->GetHLTrigger(i).trigger_word; - _ptb_hlt_timestamp[hlt_i] = ptb->GetHLTrigger(i).timestamp * 20; - - ++hlt_i; - } - } - - unsigned nLLTs = 0; - - for(auto const& ptb : PTBVec) - nLLTs += ptb->GetNLLTriggers(); - - _ptb_llt_trigger.resize(nLLTs); - _ptb_llt_timestamp.resize(nLLTs); - - unsigned llt_i = 0; - - for(auto const& ptb : PTBVec) - { - for(unsigned i = 0; i < ptb->GetNLLTriggers(); ++i) - { - _ptb_llt_trigger[llt_i] = ptb->GetLLTrigger(i).trigger_word; - _ptb_llt_timestamp[llt_i] = ptb->GetLLTrigger(i).timestamp * 20; - - ++llt_i; - } - } -} - -void sbnd::crt::CRTTopHatAnalysis::AnalyseTDCs(std::vector> &TDCVec) -{ - const unsigned nTDCs = TDCVec.size(); - - _tdc_channel.resize(nTDCs); - _tdc_timestamp.resize(nTDCs); - _tdc_offset.resize(nTDCs); - _tdc_name.resize(nTDCs); - - unsigned tdc_i = 0; - - for(auto const& tdc : TDCVec) - { - _tdc_channel[tdc_i] = tdc->Channel(); - _tdc_timestamp[tdc_i] = tdc->Timestamp(); - _tdc_offset[tdc_i] = tdc->Offset(); - _tdc_name[tdc_i] = tdc->Name(); - - ++tdc_i; - } -} - -void sbnd::crt::CRTTopHatAnalysis::SortReferencing() -{ - _etrig_good = false; _rwm_good = false; _ptb_hlt_beam_gate_good = false; _crt_t1_reset_good = false; - _rwm_etrig_diff = std::numeric_limits::max(); _ptb_hlt_beam_gate_etrig_diff = std::numeric_limits::max(); - _rwm_crt_t1_reset_diff = std::numeric_limits::max(); _ptb_hlt_beam_gate_crt_t1_reset_diff = std::numeric_limits::max(); - _rwm_ptb_hlt_beam_gate_diff = std::numeric_limits::max(); - - int etrig_count = 0, etrig_id = -1, rwm_count = 0, rwm_id = -1, crt_t1_reset_count = 0, crt_t1_reset_id = -1; - - for(unsigned int tdc_i = 0; tdc_i < _tdc_channel.size(); ++tdc_i) - { - if(_tdc_channel[tdc_i] == 4) - { - ++etrig_count; - etrig_id = tdc_i; - } - else if(_tdc_channel[tdc_i] == 2) - { - ++rwm_count; - rwm_id = tdc_i; - } - else if(_tdc_channel[tdc_i] == 0) - { - ++crt_t1_reset_count; - crt_t1_reset_id = tdc_i; - } - } - - uint64_t etrig = std::numeric_limits::max(), rwm = std::numeric_limits::max(), - hlt = std::numeric_limits::max(), crt_t1_reset = std::numeric_limits::max(); - - if(etrig_count == 1) - { - _etrig_good = true; - etrig = _tdc_timestamp[etrig_id]; - } - - if(rwm_count == 1) - { - _rwm_good = true; - rwm = _tdc_timestamp[rwm_id]; - } - - if(etrig_count == 1) - { - double closest_diff = std::numeric_limits::max(); - - for(unsigned int ptb_i = 0; ptb_i < _ptb_hlt_trigger.size(); ++ptb_i) - { - std::bitset<32> hlt_bitmask = std::bitset<32>(_ptb_hlt_trigger[ptb_i]); - - for(uint32_t allowed_hlt : fAllowedPTBHLTs) - { - if(hlt_bitmask[allowed_hlt]) - { - _ptb_hlt_beam_gate_good = true; - - uint64_t temp_hlt = _ptb_hlt_timestamp[ptb_i]; - double diff = etrig > temp_hlt ? etrig - temp_hlt : -1. * (temp_hlt - etrig); - - if(std::abs(diff) < closest_diff) - { - closest_diff = diff; - hlt = temp_hlt; - } - } - } - } - } - - if(crt_t1_reset_count == 1) - { - _crt_t1_reset_good = true; - crt_t1_reset = _tdc_timestamp[crt_t1_reset_id]; - } - - if(_etrig_good && _rwm_good) - _rwm_etrig_diff = etrig > rwm ? etrig - rwm : -1. * (rwm - etrig); - - if(_etrig_good && _ptb_hlt_beam_gate_good) - _ptb_hlt_beam_gate_etrig_diff = etrig > hlt ? etrig - hlt : -1. * (hlt - etrig); - - if(_crt_t1_reset_good && _rwm_good) - _rwm_crt_t1_reset_diff = crt_t1_reset > rwm ? crt_t1_reset - rwm : -1. * (rwm - crt_t1_reset); - - if(_etrig_good && _crt_t1_reset_good && _ptb_hlt_beam_gate_good) - _ptb_hlt_beam_gate_crt_t1_reset_diff = crt_t1_reset > hlt ? crt_t1_reset - hlt : -1. * (hlt - crt_t1_reset); - - if(_etrig_good && _rwm_good && _ptb_hlt_beam_gate_good) - _rwm_ptb_hlt_beam_gate_diff = hlt > rwm ? hlt - rwm : -1. * (rwm - hlt); -} - -void sbnd::crt::CRTTopHatAnalysis::AnalyseCRTStripHits(const art::Event &e, const std::vector> &CRTStripHitVec) -{ - _sh_channel.clear(); - _sh_tagger.clear(); - _sh_ts0.clear(); - _sh_ts0_rwm_ref.clear(); - _sh_ts0_ptb_hlt_beam_gate_ref.clear(); - _sh_ts1.clear(); - _sh_ts1_rwm_ref.clear(); - _sh_ts1_ptb_hlt_beam_gate_ref.clear(); - _sh_unixs.clear(); - _sh_pos.clear(); - _sh_err.clear(); - _sh_adc1.clear(); - _sh_adc2.clear(); - _sh_saturated1.clear(); - _sh_saturated2.clear(); - - for(auto const &hit : CRTStripHitVec) - { - if(fCutT0 && (hit->Ts0() < fMinT0 || hit->Ts0() > fMaxT0)) - continue; - - _sh_channel.push_back(hit->Channel()); - _sh_tagger.push_back(fCRTGeoService->ChannelToTaggerEnum(hit->Channel())); - _sh_ts0.push_back(hit->Ts0()); - _sh_ts0_rwm_ref.push_back(hit->Ts0() + _rwm_etrig_diff); - _sh_ts0_ptb_hlt_beam_gate_ref.push_back(hit->Ts0() + _ptb_hlt_beam_gate_etrig_diff); - _sh_ts1.push_back(hit->Ts1()); - _sh_ts1_rwm_ref.push_back(hit->Ts1() + _rwm_crt_t1_reset_diff); - _sh_ts1_ptb_hlt_beam_gate_ref.push_back(hit->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); - _sh_unixs.push_back(hit->UnixS()); - _sh_pos.push_back(hit->Pos()); - _sh_err.push_back(hit->Error()); - _sh_adc1.push_back(hit->ADC1()); - _sh_adc2.push_back(hit->ADC2()); - _sh_saturated1.push_back(hit->Saturated1()); - _sh_saturated2.push_back(hit->Saturated2()); - } -} - -void sbnd::crt::CRTTopHatAnalysis::AnalyseCRTClusters(const art::Event &e, const std::vector> &CRTClusterVec, - const art::FindManyP &clustersToSpacePoints) -{ - _cl_ts0.clear(); - _cl_ts0_rwm_ref.clear(); - _cl_ts0_ptb_hlt_beam_gate_ref.clear(); - _cl_ts1.clear(); - _cl_ts1_rwm_ref.clear(); - _cl_ts1_ptb_hlt_beam_gate_ref.clear(); - _cl_unixs.clear(); - _cl_nhits.clear(); - _cl_tagger.clear(); - _cl_composition.clear(); - _cl_has_sp.clear(); - _cl_sp_x.clear(); - _cl_sp_ex.clear(); - _cl_sp_y.clear(); - _cl_sp_ey.clear(); - _cl_sp_z.clear(); - _cl_sp_ez.clear(); - _cl_sp_pe.clear(); - _cl_sp_ts0.clear(); - _cl_sp_ts0_rwm_ref.clear(); - _cl_sp_ts0_ptb_hlt_beam_gate_ref.clear(); - _cl_sp_ets0.clear(); - _cl_sp_ts1.clear(); - _cl_sp_ts1_rwm_ref.clear(); - _cl_sp_ts1_ptb_hlt_beam_gate_ref.clear(); - _cl_sp_ets1.clear(); - _cl_sp_complete.clear(); - - for(auto const &cluster : CRTClusterVec) - { - if(fCutT0 && (cluster->Ts0() < fMinT0 || cluster->Ts0() > fMaxT0)) - continue; - - _cl_ts0.push_back(cluster->Ts0()); - _cl_ts0_rwm_ref.push_back(cluster->Ts0() + _rwm_etrig_diff); - _cl_ts0_ptb_hlt_beam_gate_ref.push_back(cluster->Ts0() + _ptb_hlt_beam_gate_etrig_diff); - _cl_ts1.push_back(cluster->Ts1()); - _cl_ts1_rwm_ref.push_back(cluster->Ts1() + _rwm_crt_t1_reset_diff); - _cl_ts1_ptb_hlt_beam_gate_ref.push_back(cluster->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); - _cl_unixs.push_back(cluster->UnixS()); - _cl_nhits.push_back(cluster->NHits()); - _cl_tagger.push_back(cluster->Tagger()); - _cl_composition.push_back(cluster->Composition()); - - const auto spacepoints = clustersToSpacePoints.at(cluster.key()); - if(spacepoints.size() == 1) - { - const auto spacepoint = spacepoints[0]; - - _cl_has_sp.push_back(true); - _cl_sp_x.push_back(spacepoint->X()); - _cl_sp_ex.push_back(spacepoint->XErr()); - _cl_sp_y.push_back(spacepoint->Y()); - _cl_sp_ey.push_back(spacepoint->YErr()); - _cl_sp_z.push_back(spacepoint->Z()); - _cl_sp_ez.push_back(spacepoint->ZErr()); - _cl_sp_pe.push_back(spacepoint->PE()); - _cl_sp_ts0.push_back(spacepoint->Ts0()); - _cl_sp_ts0_rwm_ref.push_back(spacepoint->Ts0() + _rwm_etrig_diff); - _cl_sp_ts0_ptb_hlt_beam_gate_ref.push_back(spacepoint->Ts0() + _ptb_hlt_beam_gate_etrig_diff); - _cl_sp_ets0.push_back(spacepoint->Ts0Err()); - _cl_sp_ts1.push_back(spacepoint->Ts1()); - _cl_sp_ts1_rwm_ref.push_back(spacepoint->Ts1() + _rwm_crt_t1_reset_diff); - _cl_sp_ts1_ptb_hlt_beam_gate_ref.push_back(spacepoint->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); - _cl_sp_ets1.push_back(spacepoint->Ts1Err()); - _cl_sp_complete.push_back(spacepoint->Complete()); - } - else - { - _cl_has_sp.push_back(false); - _cl_sp_x.push_back(-999999.); - _cl_sp_ex.push_back(-999999.); - _cl_sp_y.push_back(-999999.); - _cl_sp_ey.push_back(-999999.); - _cl_sp_z.push_back(-999999.); - _cl_sp_ez.push_back(-999999.); - _cl_sp_pe.push_back(-999999.); - _cl_sp_ts0.push_back(-999999.); - _cl_sp_ts0_rwm_ref.push_back(-999999.); - _cl_sp_ts0_ptb_hlt_beam_gate_ref.push_back(-999999.); - _cl_sp_ets0.push_back(-999999.); - _cl_sp_ts1.push_back(-999999.); - _cl_sp_ts1_rwm_ref.push_back(-999999.); - _cl_sp_ts1_ptb_hlt_beam_gate_ref.push_back(-999999.); - _cl_sp_ets1.push_back(-999999.); - _cl_sp_complete.push_back(false); - } - } -} -void sbnd::crt::CRTTopHatAnalysis::AnalyseCRTTracks(const art::Event &e, const std::vector> &CRTTrackVec) -{ - _tr_start_x.clear(); - _tr_start_y.clear(); - _tr_start_z.clear(); - _tr_end_x.clear(); - _tr_end_y.clear(); - _tr_end_z.clear(); - _tr_dir_x.clear(); - _tr_dir_y.clear(); - _tr_dir_z.clear(); - _tr_ts0.clear(); - _tr_ts0_rwm_ref.clear(); - _tr_ts0_ptb_hlt_beam_gate_ref.clear(); - _tr_ets0.clear(); - _tr_ts1.clear(); - _tr_ts1_rwm_ref.clear(); - _tr_ts1_ptb_hlt_beam_gate_ref.clear(); - _tr_ets1.clear(); - _tr_pe.clear(); - _tr_length.clear(); - _tr_tof.clear(); - _tr_theta.clear(); - _tr_phi.clear(); - _tr_triple.clear(); - _tr_tagger1.clear(); - _tr_tagger2.clear(); - _tr_tagger3.clear(); - - for(auto const& track : CRTTrackVec) - { - if(fCutT0 && (track->Ts0() < fMinT0 || track->Ts0() > fMaxT0)) - continue; - - const geo::Point_t start = track->Start(); - _tr_start_x.push_back(start.X()); - _tr_start_y.push_back(start.Y()); - _tr_start_z.push_back(start.Z()); - - const geo::Point_t end = track->End(); - _tr_end_x.push_back(end.X()); - _tr_end_y.push_back(end.Y()); - _tr_end_z.push_back(end.Z()); - - const geo::Vector_t dir = track->Direction(); - _tr_dir_x.push_back(dir.X()); - _tr_dir_y.push_back(dir.Y()); - _tr_dir_z.push_back(dir.Z()); - - _tr_ts0.push_back(track->Ts0()); - _tr_ts0_rwm_ref.push_back(track->Ts0() + _rwm_etrig_diff); - _tr_ts0_ptb_hlt_beam_gate_ref.push_back(track->Ts0() + _ptb_hlt_beam_gate_etrig_diff); - _tr_ets0.push_back(track->Ts0Err()); - _tr_ts1.push_back(track->Ts1()); - _tr_ts1_rwm_ref.push_back(track->Ts1() + _rwm_crt_t1_reset_diff); - _tr_ts1_ptb_hlt_beam_gate_ref.push_back(track->Ts1() + _ptb_hlt_beam_gate_crt_t1_reset_diff); - _tr_ets1.push_back(track->Ts1Err()); - _tr_pe.push_back(track->PE()); - _tr_length.push_back(track->Length()); - _tr_tof.push_back(track->ToF()); - _tr_theta.push_back(TMath::RadToDeg() * track->Theta()); - _tr_phi.push_back(TMath::RadToDeg() * track->Phi()); - _tr_triple.push_back(track->Triple()); - - unsigned tag_i = 0; - - for(auto const &tagger : track->Taggers()) - { - if(tag_i == 0) - _tr_tagger1.push_back(tagger); - else if(tag_i == 1) - _tr_tagger2.push_back(tagger); - else if(tag_i == 2) - _tr_tagger3.push_back(tagger); - - ++tag_i; - } - } -} - -void sbnd::crt::CRTTopHatAnalysis::AnalysePMTSoftwareTriggers(const art::Event &e, const std::vector> &PMTSoftwareTriggerVec) -{ - _pmt_st_found_trigger = false; - _pmt_st_corrected_peak_time = std::numeric_limits::lowest(); - _pmt_st_corrected_peak_time_rwm_ref = std::numeric_limits::lowest(); - - if(PMTSoftwareTriggerVec.size() != 1) - return; - - _pmt_st_found_trigger = PMTSoftwareTriggerVec[0]->foundBeamTrigger; - _pmt_st_corrected_peak_time = PMTSoftwareTriggerVec[0]->peaktime*1e3 + PMTSoftwareTriggerVec[0]->trig_ts; - _pmt_st_corrected_peak_time_rwm_ref = _pmt_st_corrected_peak_time + _rwm_ptb_hlt_beam_gate_diff; -} - -DEFINE_ART_MODULE(sbnd::crt::CRTTopHatAnalysis) diff --git a/sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl b/sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl deleted file mode 100644 index a82b14e43..000000000 --- a/sbndcode/CRT/CRTAna/crttophatana_sbnd.fcl +++ /dev/null @@ -1,12 +0,0 @@ -BEGIN_PROLOG - -crttophatana_data_sbnd: -{ - module_type: "CRTTopHatAnalysis" - CutT0: true - MinT0: -50000 - MaxT0: 50000 - SavePMTSoftwareTrigger: true -} - -END_PROLOG diff --git a/sbndcode/CRT/CRTAna/run_crttophatana_data.fcl b/sbndcode/CRT/CRTAna/run_crttophatana_data.fcl deleted file mode 100644 index cce367369..000000000 --- a/sbndcode/CRT/CRTAna/run_crttophatana_data.fcl +++ /dev/null @@ -1,28 +0,0 @@ -#include "services_sbnd.fcl" -#include "crt_services_sbnd.fcl" -#include "crttophatana_sbnd.fcl" - -process_name: CRTTopHatAna - -services: -{ - TFileService: { fileName: "crttophatana_sbnd.root" } - @table::sbnd_basic_services - @table::crt_services_data_sbnd -} - -source: -{ - module_type: RootInput -} - -physics: -{ - analyzers: - { - crttophatana: @local::crttophatana_data_sbnd - } - - ana: [ crttophatana ] - end_paths: [ ana ] -} From cb47ee9171633c83ae098ccb6694115edfa91bce Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Fri, 27 Feb 2026 05:32:58 -0600 Subject: [PATCH 63/75] Remove reference to my data area --- sbndcode/CRT/CRTAna/adrift_sbnd.fcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbndcode/CRT/CRTAna/adrift_sbnd.fcl b/sbndcode/CRT/CRTAna/adrift_sbnd.fcl index 0be839450..8113032ed 100644 --- a/sbndcode/CRT/CRTAna/adrift_sbnd.fcl +++ b/sbndcode/CRT/CRTAna/adrift_sbnd.fcl @@ -10,7 +10,7 @@ adrift_data_sbnd: CRTTrackModuleLabel: "crttracks" DAQHeaderModuleLabel: "daq" DAQHeaderInstanceLabel: "RawEventHeader" - TopSaveDirectory: "/exp/sbnd/data/users/hlay/crt_comm_summer_2024/plots/adrift" + TopSaveDirectory: "/ENTER/YOUR/SAVE/DIRECTORY/HERE" Only2HitSpacePoints: false SaveAllFits: false SaveBadFits: false From bdf38e4bdde296074246f68ec0f6189ac1a637b9 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Fri, 27 Feb 2026 05:44:38 -0600 Subject: [PATCH 64/75] Reduce code duplication --- sbndcode/CRT/CRTAna/CRTAnalysis_module.cc | 42 ++++++----------------- sbndcode/CRT/CRTAna/crtana_sbnd.fcl | 24 ++++++------- 2 files changed, 22 insertions(+), 44 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc index 08b1f8202..4849708f2 100644 --- a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc @@ -37,13 +37,13 @@ #include "sbnobj/SBND/Timing/DAQTimestamp.hh" #include "sbndcode/Geometry/GeometryWrappers/CRTGeoService.h" -#include "sbndcode/Geometry/GeometryWrappers/TPCGeoAlg.h" #include "sbndcode/ChannelMaps/CRT/CRTChannelMapService.h" #include "sbndcode/CRT/CRTBackTracker/CRTBackTrackerAlg.h" #include "sbndcode/CRT/CRTUtils/CRTCommonUtils.h" #include "sbndcode/CRT/CRTUtils/TPCGeoUtil.h" #include "sbndcode/Decoders/PTB/sbndptb.h" #include "sbndcode/Timing/SBNDRawTimingObj.h" +#include "sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h" namespace sbnd::crt { class CRTAnalysis; @@ -103,16 +103,14 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { art::ServiceHandle fCRTGeoService; art::ServiceHandle fCRTChannelMapService; - TPCGeoAlg fTPCGeoAlg; - CRTBackTrackerAlg fCRTBackTrackerAlg; + CRTBackTrackerAlg fCRTBackTrackerAlg; + CRTClusterCharacterisationAlg fCRTClusterCharacAlg; std::string fMCParticleModuleLabel, fSimDepositModuleLabel, fFEBDataModuleLabel, fCRTStripHitModuleLabel, fCRTClusterModuleLabel, fCRTSpacePointModuleLabel, fCRTTrackModuleLabel, fCRTBlobModuleLabel, fTPCTrackModuleLabel, fCRTSpacePointMatchingModuleLabel, fCRTTrackMatchingModuleLabel, fPFPModuleLabel, fPTBModuleLabel, fTDCModuleLabel, fTimingReferenceModuleLabel; bool fDebug, fDataMode, fNoTPC, fHasPTB, fHasTDC, fHasBlobs, fTruthMatch; - //! Adding some of the reco parameters to save corrections - double fPEAttenuation, fTimeWalkNorm, fTimeWalkScale, fPropDelay; TTree* fTree; @@ -197,11 +195,11 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _cl_composition; std::vector> _cl_channel_set; std::vector> _cl_adc_set; - std::vector> _cl_sh_ts0_set; //! To store t0 from x-y coincidences - std::vector> _cl_sh_ts1_set; //! To store t1 from x-y coincidences - std::vector> _cl_sh_feb_mac5_set; //! MAC5 addresses of StripHit FEBs - std::vector> _cl_sh_time_walk_set; //! Time walk correction - std::vector> _cl_sh_prop_delay_set; //! Light propagation correction + std::vector> _cl_sh_ts0_set; + std::vector> _cl_sh_ts1_set; + std::vector> _cl_sh_feb_mac5_set; + std::vector> _cl_sh_time_walk_set; + std::vector> _cl_sh_prop_delay_set; std::vector _cl_truth_trackid; std::vector _cl_truth_completeness; std::vector _cl_truth_purity; @@ -372,6 +370,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) : EDAnalyzer{p} , fCRTBackTrackerAlg(p.get("CRTBackTrackerAlg", fhicl::ParameterSet())) + , fCRTClusterCharacAlg(p.get("CRTClusterCharacterisationAlg", fhicl::ParameterSet())) { fMCParticleModuleLabel = p.get("MCParticleModuleLabel", "largeant"); fSimDepositModuleLabel = p.get("SimDepositModuleLabel", "genericcrt"); @@ -395,10 +394,6 @@ sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) fHasTDC = p.get("HasTDC", false); fHasBlobs = p.get("HasBlobs", false); fTruthMatch = p.get("TruthMatch", true); - fPEAttenuation = p.get("PEAttenuation", 1.0); - fTimeWalkNorm = p.get("TimeWalkNorm", 0.0); - fTimeWalkScale = p.get("TimeWalkScale", 0.0); - fPropDelay = p.get("PropDelay", 0.0); if(!fDataMode && fTruthMatch) fCRTBackTrackerAlg = CRTBackTrackerAlg(p.get("CRTBackTrackerAlg", fhicl::ParameterSet())); @@ -1328,25 +1323,10 @@ void sbnd::crt::CRTAnalysis::AnalyseCRTClusters(const art::Event &e, const std:: _cl_sh_ts1_set[i][ii] = striphit->Ts1(); _cl_sh_feb_mac5_set[i][ii] = fCRTChannelMapService->GetMAC5FromOfflineChannelID(striphit->Channel()); - /* - * The below segment reimplements the CorrectTime() method - * from CRTReco/CRTClusterCharacterisationAlg.cc . - * Because the Ts0(), Ts1() getters invoked in _cl_sp_ts*, _cl_sh_ts*_set are raw T0/1 - * counters, the time walk and propagation delay are saved as explicit branches here. - */ if(spacepoints.size() == 1) { - double pe0 = fCRTGeoService->GetSiPM( striphit->Channel() ).gain * striphit->ADC1(); - double pe1 = fCRTGeoService->GetSiPM( striphit->Channel() + 1 ).gain * striphit->ADC2(); - double pe = pe0 + pe1; - - double dist = fCRTGeoService->DistanceDownStrip( spacepoints[0]->Pos(), striphit->Channel() ); - - double corr = std::pow( dist - fPEAttenuation, 2.0 ) / std::pow( fPEAttenuation, 2.0 ); - double tw_pe = pe * corr; - - _cl_sh_time_walk_set[i][ii] = fTimeWalkNorm * std::exp( -fTimeWalkScale * tw_pe ); - _cl_sh_prop_delay_set[i][ii] = fPropDelay * dist; + _cl_sh_time_walk_set[i][ii] = fCRTClusterCharacAlg.TimeWalk(striphit, spacepoints[0]->Pos()); + _cl_sh_prop_delay_set[i][ii] = fCRTClusterCharacAlg.PropagationDelay(striphit, spacepoints[0]->Pos()); ts0_set.push_back({_cl_sh_feb_mac5_set[i][ii], _cl_sh_ts0_set[i][ii] - _cl_sh_time_walk_set[i][ii] - _cl_sh_prop_delay_set[i][ii]}); ts1_set.push_back({_cl_sh_feb_mac5_set[i][ii], _cl_sh_ts1_set[i][ii] - _cl_sh_time_walk_set[i][ii] - _cl_sh_prop_delay_set[i][ii]}); diff --git a/sbndcode/CRT/CRTAna/crtana_sbnd.fcl b/sbndcode/CRT/CRTAna/crtana_sbnd.fcl index 1ab588870..f319bc4df 100644 --- a/sbndcode/CRT/CRTAna/crtana_sbnd.fcl +++ b/sbndcode/CRT/CRTAna/crtana_sbnd.fcl @@ -1,24 +1,22 @@ #include "crtbacktrackeralg_sbnd.fcl" -#include "crtsimmodules_sbnd.fcl" +#include "crtrecoproducers_sbnd.fcl" BEGIN_PROLOG crtana_sbnd: { - CRTBackTrackerAlg: @local::crtbacktrackeralg_sbnd - PEAttenuation: @local::sbnd_crtsim.DetSimParams.NpeScaleShift - PropDelay: @local::sbnd_crtsim.DetSimParams.PropDelay - TimeWalkNorm: @local::sbnd_crtsim.DetSimParams.TDelayNorm - TimeWalkScale: @local::sbnd_crtsim.DetSimParams.TDelayScale - TruthMatch: false - module_type: "CRTAnalysis" + CRTBackTrackerAlg: @local::crtbacktrackeralg_sbnd + CRTClusterCharacterisationAlg: @local::crtclustercharacterisationalg_sbnd + TruthMatch: false + module_type: "CRTAnalysis" } crtana_data_sbnd: @local::crtana_sbnd -crtana_data_sbnd.FEBDataModuleLabel: "crtdecoder" -crtana_data_sbnd.DataMode: true -crtana_data_sbnd.NoTPC: false -crtana_data_sbnd.HasPTB: true -crtana_data_sbnd.HasTDC: true +crtana_data_sbnd.FEBDataModuleLabel: "crtdecoder" +crtana_data_sbnd.DataMode: true +crtana_data_sbnd.NoTPC: false +crtana_data_sbnd.HasPTB: true +crtana_data_sbnd.HasTDC: true +crtana_data_sbnd.CRTClusterCharacterisationAlg: @local::crtclustercharacterisationalg_data_sbnd END_PROLOG From 8efaff2023309dda9eee806bbcfdb64b12df2cda Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Fri, 27 Feb 2026 05:56:51 -0600 Subject: [PATCH 65/75] Correct some very old naming problems --- sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h b/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h index 373d47ed7..97b3133f7 100644 --- a/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h +++ b/sbndcode/CRT/CRTReco/CRTClusterCharacterisationAlg.h @@ -1,10 +1,9 @@ -#ifndef CRTBACKTRACKERALG_H_SEEN -#define CRTBACKTRACKERALG_H_SEEN +#ifndef CRTCLUSTERCHARACTERISATIONALG_H_SEEN +#define CRTCLUSTERCHARACTERISATIONALG_H_SEEN /////////////////////////////////////////////// // CRTClusterCharacterisationAlg.h // -// Truth Matching Utilities for CRT analysis // Henry Lay (h.lay@lancaster.ac.uk) // November 2022 /////////////////////////////////////////////// From 076fc35a786403595db0e3aacc41c4cbdba03c38 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 3 Mar 2026 07:25:01 -0600 Subject: [PATCH 66/75] Add rate for tracks of limited angle --- sbndcode/CRT/CRTAna/ADRIFT_module.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sbndcode/CRT/CRTAna/ADRIFT_module.cc b/sbndcode/CRT/CRTAna/ADRIFT_module.cc index 01727c94a..8725c472d 100644 --- a/sbndcode/CRT/CRTAna/ADRIFT_module.cc +++ b/sbndcode/CRT/CRTAna/ADRIFT_module.cc @@ -117,7 +117,7 @@ class sbnd::crt::ADRIFT : public art::EDAnalyzer { uint64_t _unix_start, _unix_end; int _n_events, _channel, _gdml_id, _mac5, _raw_channel, _tagger, _channel_status; double _area, _y_average, _ped_calib, _gain_calib, _ped_fit, _ped_fit_std, _ped_fit_chi2, _ped_peak, - _ped_reset_fit, _ped_reset_fit_std, _ped_reset_fit_chi2, _ped_reset_peak, _raw_max_chan_rate, _sh_rate, _sp_rate, _tr_rate, + _ped_reset_fit, _ped_reset_fit_std, _ped_reset_fit_chi2, _ped_reset_peak, _raw_max_chan_rate, _sh_rate, _sp_rate, _tr_rate, _tr_lim_angle_rate, _sh_peak_fit, _sh_peak_fit_chi2, _sh_peak_peak, _sh_pe_peak_fit, _sh_pe_peak_fit_chi2, _sh_pe_peak_peak, _sh_sat_rate, _sh_sat_ratio_total, _sh_sat_ratio_peak, _sp_peak_fit, _sp_peak_fit_chi2, _sp_peak_peak, _sp_pe_peak_fit, _sp_pe_peak_fit_chi2, _sp_pe_peak_peak, _sp_sat_rate, _sp_sat_ratio_total, _sp_sat_ratio_peak, @@ -270,6 +270,7 @@ sbnd::crt::ADRIFT::ADRIFT(fhicl::ParameterSet const& p) } if(fTrackLA) { + fChannelTree->Branch("tr_lim_angle_rate", &_tr_lim_angle_rate); fChannelTree->Branch("tr_lim_angle_peak_fit", &_tr_lim_angle_peak_fit); fChannelTree->Branch("tr_lim_angle_peak_fit_chi2", &_tr_lim_angle_peak_fit_chi2); fChannelTree->Branch("tr_lim_angle_peak_fit_converged", &_tr_lim_angle_peak_fit_converged); @@ -992,6 +993,8 @@ void sbnd::crt::ADRIFT::ProcessEntry(const int ch, const int window) if(fTrackLA && _tagger != kBottomTagger) { + Rate(hADCTrLA[window][ch], _tr_lim_angle_rate, window, fReconstructionWindow); + PeakPeak(hADCTrLA[window][ch], _ped_calib, _tr_lim_angle_peak_peak); PeakFit(hADCTrLA[window][ch], _tr_lim_angle_peak_peak, _ped_calib, _tr_lim_angle_peak_fit, _tr_lim_angle_peak_fit_chi2, _tr_lim_angle_peak_fit_converged, _channel_status, window); @@ -1302,6 +1305,7 @@ void sbnd::crt::ADRIFT::ResetVars() _tr_by_length_peak_fit = std::numeric_limits::lowest(); _tr_by_length_peak_fit_chi2 = std::numeric_limits::lowest(); _tr_by_length_peak_peak = std::numeric_limits::lowest(); + _tr_lim_angle_rate = std::numeric_limits::lowest(); _tr_lim_angle_peak_fit = std::numeric_limits::lowest(); _tr_lim_angle_peak_fit_chi2 = std::numeric_limits::lowest(); _tr_lim_angle_peak_peak = std::numeric_limits::lowest(); From c505fdaec1a03b3cb95f3e51e55bd86253578de7 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Tue, 3 Mar 2026 07:25:24 -0600 Subject: [PATCH 67/75] Add xshift for CRT-TPC track matching --- sbndcode/CRT/CRTAna/CRTAnalysis_module.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc index 4849708f2..318553eca 100644 --- a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc @@ -342,6 +342,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _tpc_tr_matchable; std::vector _tpc_tr_matched; std::vector _tpc_tr_good_match; + std::vector _tpc_tr_xshift; std::vector _tpc_tr_ts0; std::vector _tpc_tr_ts1; std::vector> _tpc_tr_taggers; @@ -630,6 +631,7 @@ sbnd::crt::CRTAnalysis::CRTAnalysis(fhicl::ParameterSet const& p) fTree->Branch("tpc_sp_z", "std::vector", &_tpc_sp_z); fTree->Branch("tpc_sp_score", "std::vector", &_tpc_sp_score); fTree->Branch("tpc_tr_matched", "std::vector", &_tpc_tr_matched); + fTree->Branch("tpc_tr_xshift", "std::vector", &_tpc_tr_xshift); fTree->Branch("tpc_tr_ts0", "std::vector", &_tpc_tr_ts0); fTree->Branch("tpc_tr_ts1", "std::vector", &_tpc_tr_ts1); fTree->Branch("tpc_tr_taggers", "std::vector>", &_tpc_tr_taggers); @@ -1685,6 +1687,7 @@ void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art:: _tpc_tr_matchable.resize(nTracks); _tpc_tr_matched.resize(nTracks); _tpc_tr_good_match.resize(nTracks); + _tpc_tr_xshift.resize(nTracks); _tpc_tr_ts0.resize(nTracks); _tpc_tr_ts1.resize(nTracks); _tpc_tr_taggers.resize(nTracks); @@ -1797,7 +1800,11 @@ void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art:: { const anab::T0 trackMatch = tracksToTrackMatches.data(track.key()).ref(); + const int driftDirection = TPCGeoUtil::DriftDirectionFromHits(geometryService, trackHits); + const double crtShiftingTime = fDataMode ? crttrack->Ts0() * 1e-3 : crttrack->Ts1() * 1e-3; + _tpc_tr_matched[nActualTracks] = true; + _tpc_tr_xshift[nActualTracks] = driftDirection * crtShiftingTime * detProp.DriftVelocity(); _tpc_tr_ts0[nActualTracks] = crttrack->Ts0(); _tpc_tr_ts1[nActualTracks] = crttrack->Ts1(); _tpc_tr_score[nActualTracks] = trackMatch.TriggerConfidence(); @@ -1821,6 +1828,7 @@ void sbnd::crt::CRTAnalysis::AnalyseTPCMatching(const art::Event &e, const art:: else { _tpc_tr_matched[nActualTracks] = false; + _tpc_tr_xshift[nActualTracks] = -std::numeric_limits::max(); _tpc_tr_ts0[nActualTracks] = -std::numeric_limits::max(); _tpc_tr_ts1[nActualTracks] = -std::numeric_limits::max(); _tpc_tr_score[nActualTracks] = -std::numeric_limits::max(); From 2771a929c487217817ca66e1cda783d68aafcbe1 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 5 Mar 2026 05:15:09 -0600 Subject: [PATCH 68/75] Add track direction branches to spacepoint timing tree --- .../CRT/CRTAna/CRTTimingAnalysis_module.cc | 38 +++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc index 73846af9c..f050cce6c 100644 --- a/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTTimingAnalysis_module.cc @@ -70,7 +70,8 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { void AnalyseCRTSpacePoints(const std::vector> &CRTSpacePointVec, const art::FindOneP &spacepointsToClusters, - const art::FindManyP &clustersToStripHits); + const art::FindManyP &clustersToStripHits, + const art::FindOneP &spacepointsToTracks); void ResetSPVariables(); @@ -171,6 +172,9 @@ class sbnd::crt::CRTTimingAnalysis : public art::EDAnalyzer { std::vector _sp_sh_calib_offset_ts0_set; std::vector _sp_sh_cable_length_ts1_set; std::vector _sp_sh_calib_offset_ts1_set; + bool _sp_has_track; + double _sp_norm_angle; + double _sp_path_length; double _tr_start_x; double _tr_start_y; @@ -324,6 +328,9 @@ sbnd::crt::CRTTimingAnalysis::CRTTimingAnalysis(fhicl::ParameterSet const& p) fSPTree->Branch("sp_sh_calib_offset_ts0_set", "std::vector", &_sp_sh_calib_offset_ts0_set); fSPTree->Branch("sp_sh_cable_length_ts1_set", "std::vector", &_sp_sh_cable_length_ts1_set); fSPTree->Branch("sp_sh_calib_offset_ts1_set", "std::vector", &_sp_sh_calib_offset_ts1_set); + fSPTree->Branch("sp_has_track", &_sp_has_track); + fSPTree->Branch("sp_norm_angle", &_sp_norm_angle); + fSPTree->Branch("sp_path_length", &_sp_path_length); fTrTree = fs->make("tracks",""); fTrTree->Branch("run", &_run); @@ -495,6 +502,9 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) // Get CRTSpacePoint to CRTCluster Assns art::FindOneP spacepointsToClusters(CRTSpacePointHandle, e, fCRTSpacePointModuleLabel); + // Get CRTSpacePoint to CRTTrack Assns + art::FindOneP spacepointsToTracks(CRTSpacePointHandle, e, fCRTTrackModuleLabel); + // Get CRTClusters art::Handle> CRTClusterHandle; e.getByLabel(fCRTClusterModuleLabel, CRTClusterHandle); @@ -507,7 +517,7 @@ void sbnd::crt::CRTTimingAnalysis::analyze(art::Event const& e) art::FindManyP clustersToStripHits(CRTClusterHandle, e, fCRTClusterModuleLabel); // Fill CRTSpacePoint variables - AnalyseCRTSpacePoints(CRTSpacePointVec, spacepointsToClusters, clustersToStripHits); + AnalyseCRTSpacePoints(CRTSpacePointVec, spacepointsToClusters, clustersToStripHits, spacepointsToTracks); // Get CRTTracks art::Handle> CRTTrackHandle; @@ -736,13 +746,15 @@ void sbnd::crt::CRTTimingAnalysis::SortReferencing() void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vector> &CRTSpacePointVec, const art::FindOneP &spacepointsToClusters, - const art::FindManyP &clustersToStripHits) + const art::FindManyP &clustersToStripHits, + const art::FindOneP &spacepointsToTracks) { for(auto const& sp : CRTSpacePointVec) { ResetSPVariables(); const art::Ptr cl = spacepointsToClusters.at(sp.key()); + const art::Ptr tr = spacepointsToTracks.at(sp.key()); const std::vector> shs = clustersToStripHits.at(cl.key()); const unsigned n_shs = shs.size(); @@ -790,6 +802,23 @@ void sbnd::crt::CRTTimingAnalysis::AnalyseCRTSpacePoints(const std::vectorDirection().X(), tr->Direction().Y(), tr->Direction().Z()); + _sp_norm_angle = TMath::RadToDeg() * normal.Angle(tr_dir); + _sp_path_length = 1. / TMath::Cos(normal.Angle(tr_dir)); + } + fSPTree->Fill(); fSPTaggerMap[sp.key()] = _sp_tagger; @@ -824,8 +853,11 @@ void sbnd::crt::CRTTimingAnalysis::ResetSPVariables() _sp_ts1_rwm_ref_front_face = std::numeric_limits::lowest(); _sp_ts1_ptb_hlt_beam_gate_ref_front_face = std::numeric_limits::lowest(); _sp_dts1 = std::numeric_limits::lowest(); + _sp_norm_angle = std::numeric_limits::lowest(); + _sp_path_length = std::numeric_limits::lowest(); _sp_single_timing_chain = false; + _sp_has_track = false; _sp_sh_channel_set.clear(); _sp_sh_mac5_set.clear(); From a8353e26486a6b18c90e1a44f6ff3aa0bee39a48 Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 5 Mar 2026 05:20:36 -0600 Subject: [PATCH 69/75] If we're going to do comments lets get them right --- sbndcode/CRT/CRTAna/CRTAnalysis_module.cc | 24 ++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc index 318553eca..7c26b2421 100644 --- a/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc +++ b/sbndcode/CRT/CRTAna/CRTAnalysis_module.cc @@ -122,7 +122,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { int _crt_timing_reference_type; int _crt_timing_reference_channel; - //mc truth + // True Particles (from G4) std::vector _mc_trackid; std::vector _mc_pdg; std::vector _mc_status; @@ -145,7 +145,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _mc_endpz; std::vector _mc_ende; - //G4 detector id + // True Energy Depositions std::vector _ide_trackid; std::vector _ide_e; std::vector _ide_entryx; @@ -157,7 +157,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _ide_exitz; std::vector _ide_exitt; - //front end mother board + // Raw Readouts (FEBDatas) std::vector _feb_mac5; std::vector _feb_tagger; std::vector _feb_flags; @@ -167,7 +167,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector> _feb_adc; std::vector _feb_coinc; - //strip hit to select the strip which has ADC above threshold + // Strip Hits std::vector _sh_channel; std::vector _sh_tagger; std::vector _sh_ts0; @@ -186,7 +186,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _sh_truth_energy; std::vector _sh_truth_time; - //cluster from x-y coincidence for CRTSpacePoint , this is what we normally call a CRT hit + // Clusters and their corresponding SpacePoints std::vector _cl_ts0; std::vector _cl_ts1; std::vector _cl_unixs; @@ -232,7 +232,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _cl_sp_dts1; std::vector _cl_sp_complete; - //backtrack truth information from reco level + // True Deposits per particle per tagger std::vector _td_tag_trackid; std::vector _td_tag_pdg; std::vector _td_tag_tagger; @@ -243,6 +243,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _td_tag_z; std::vector _td_tag_reco_status; + // True Deposits per particle std::vector _td_trackid; std::vector _td_pdg; std::vector _td_energy; @@ -251,7 +252,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _td_reco_status; std::vector _td_reco_triple; - //track level information + // Tracks std::vector _tr_start_x; std::vector _tr_start_y; std::vector _tr_start_z; @@ -297,7 +298,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _tr_truth_theta; std::vector _tr_truth_phi; - // crt blob information + // Blobs std::vector _bl_ts0; std::vector _bl_ets0; std::vector _bl_ts1; @@ -306,7 +307,7 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _bl_nsps; std::vector> _bl_nsps_per_tagger; - // tpc track information (including crt matching) + // TPC Tracks and their CRT matches std::vector _tpc_start_x; std::vector _tpc_start_y; std::vector _tpc_start_z; @@ -354,14 +355,15 @@ class sbnd::crt::CRTAnalysis : public art::EDAnalyzer { std::vector _tpc_tr_end_z; std::vector _tpc_tr_score; - // ptb information (trigger board) + // Penn Trigger Board HLTs std::vector _ptb_hlt_trigger; std::vector _ptb_hlt_timestamp; + // Penn Trigger Board LLTs std::vector _ptb_llt_trigger; std::vector _ptb_llt_timestamp; - // spec tdc information (timing board) + // SPEC TDC Timestamps std::vector _tdc_channel; std::vector _tdc_timestamp; std::vector _tdc_offset; From 1dd3071b79f40903c3253879d0b5fa5302546c3c Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 5 Mar 2026 05:20:53 -0600 Subject: [PATCH 70/75] Add README to point to documentation --- sbndcode/CRT/CRTAna/README.md | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 sbndcode/CRT/CRTAna/README.md diff --git a/sbndcode/CRT/CRTAna/README.md b/sbndcode/CRT/CRTAna/README.md new file mode 100644 index 000000000..7b7e26cf3 --- /dev/null +++ b/sbndcode/CRT/CRTAna/README.md @@ -0,0 +1,3 @@ +# CRT Analysis Modules + +Details of these modules and the outputs (trees, branches, histograms) can be found in [docDB#45886](https://sbn-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=45886) From 3e9df7916a78ed7c69980398f7efd16b267f8cac Mon Sep 17 00:00:00 2001 From: Henry Lay Date: Thu, 5 Mar 2026 05:30:50 -0600 Subject: [PATCH 71/75] Make safer - at John's suggestion --- sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc b/sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc index 93eb61bfa..7a4891dab 100644 --- a/sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc +++ b/sbndcode/CRT/CRTReco/CRTStripHitProducer_module.cc @@ -276,8 +276,8 @@ std::vector sbnd::crt::CRTStripHitProducer::CreateStripH const uint16_t adc2 = sipm2.pedestal < sipm_adcs[adc_i+1] ? sipm_adcs[adc_i+1] - sipm2.pedestal : 0; // Saturated? - const bool sat1 = sipm_adcs[adc_i] == fADCSaturation; - const bool sat2 = sipm_adcs[adc_i+1] == fADCSaturation; + const bool sat1 = sipm_adcs[adc_i] >= fADCSaturation; + const bool sat2 = sipm_adcs[adc_i+1] >= fADCSaturation; // Keep hit if both SiPMs above threshold if(adc1 > fADCThreshold && adc2 > fADCThreshold) From b9c9abf1c71d2e76205e41629ecf587feac19f32 Mon Sep 17 00:00:00 2001 From: Sabrina Brickner Date: Sat, 7 Mar 2026 03:06:21 -0600 Subject: [PATCH 72/75] updating memory and cpu usage error bounds for CI tests --- test/ci/ci_tests.cfg | 68 ++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/test/ci/ci_tests.cfg b/test/ci/ci_tests.cfg index b46e5fb1b..bb48e0c77 100644 --- a/test/ci/ci_tests.cfg +++ b/test/ci/ci_tests.cfg @@ -319,8 +319,8 @@ STAGE_NAME=detsim INPUT_STAGE_NAME=g4 NEVENTS=2 # calibrated on sbndbuild01.fnal.gov on 20180305 -cpu_usage_range=200:700 -mem_usage_range=1000000:3000000 +cpu_usage_range=200:2390 +mem_usage_range=1000000:7232311 script=%(EXPSCRIPT_SBNDCODE)s FHiCL_FILE=%(CI_FHICL_PREFIX_SBNDCODE)ssingle_%(STAGE_NAME)s_quick_test_sbndcode.fcl @@ -383,7 +383,7 @@ STAGE_NAME=caf INPUT_STAGE_NAME=reco2 NEVENTS=5 # calibrated on sbndbuild01.fnal.gov on 20180306 -cpu_usage_range=50:200 +cpu_usage_range=50:213 mem_usage_range=500000:3500000 script=%(EXPSCRIPT_SBNDCODE)s @@ -454,7 +454,7 @@ STAGE_NAME=gen NEVENTS=%(NEVENTS_SEQ_SINGLE_SBNDCODE)s # calibrated on sbndbuild01.fnal.gov on 20180305 cpu_usage_range=10:102 -mem_usage_range=500000:700000 +mem_usage_range=500000:1069026 script=%(EXPSCRIPT_SBNDCODE)s @@ -475,8 +475,8 @@ STAGE_NAME=g4 INPUT_STAGE_NAME=gen NEVENTS=%(NEVENTS_SEQ_SINGLE_SBNDCODE)s # calibrated on sbndbuild01.fnal.gov on 20180305 -cpu_usage_range=1200:1600 -mem_usage_range=3500000:4500000 +cpu_usage_range=812:1600 +mem_usage_range=2543381:4500000 script=%(EXPSCRIPT_SBNDCODE)s requires=single_%(INPUT_STAGE_NAME)s_seq_test_sbndcode @@ -498,8 +498,8 @@ STAGE_NAME=detsim INPUT_STAGE_NAME=g4 NEVENTS=%(NEVENTS_SEQ_SINGLE_SBNDCODE)s # calibrated on sbndbuild01.fnal.gov on 20180305 -cpu_usage_range=1050:1200 -mem_usage_range=3000000:4500000 +cpu_usage_range=1050:3593 +mem_usage_range=3000000:7518172 script=%(EXPSCRIPT_SBNDCODE)s requires=single_%(INPUT_STAGE_NAME)s_seq_test_sbndcode @@ -521,7 +521,7 @@ STAGE_NAME=reco1 INPUT_STAGE_NAME=detsim NEVENTS=%(NEVENTS_SEQ_SINGLE_SBNDCODE)s # calibrated on sbndbuild01.fnal.gov on 20180306 -cpu_usage_range=300:450 +cpu_usage_range=300:1204 mem_usage_range=2500000:4000000 script=%(EXPSCRIPT_SBNDCODE)s @@ -544,8 +544,8 @@ STAGE_NAME=reco2 INPUT_STAGE_NAME=reco1 NEVENTS=%(NEVENTS_SEQ_SINGLE_SBNDCODE)s # calibrated on sbndbuild01.fnal.gov on 20180306 -cpu_usage_range=1900:2200 -mem_usage_range=2000000:3500000 +cpu_usage_range=195:2200 +mem_usage_range=1866932:3500000 script=%(EXPSCRIPT_SBNDCODE)s requires=single_%(INPUT_STAGE_NAME)s_seq_test_sbndcode @@ -684,8 +684,8 @@ STAGE_NAME=detsim INPUT_STAGE_NAME=g4 NEVENTS=2 # calibrated on sbndbuild01.fnal.gov on 20180305 -cpu_usage_range=400:1000 -mem_usage_range=1000000:3000000 +cpu_usage_range=400:2573 +mem_usage_range=1000000:7354036 script=%(EXPSCRIPT_SBNDCODE)s FHiCL_FILE=%(CI_FHICL_PREFIX_SBNDCODE)snucosmics_%(STAGE_NAME)s_quick_test_sbndcode.fcl @@ -728,7 +728,7 @@ STAGE_NAME=reco2 INPUT_STAGE_NAME=reco1 NEVENTS=2 # calibrated on sbndbuild01.fnal.gov on 20180305 -cpu_usage_range=50:1250 +cpu_usage_range=50:1366 mem_usage_range=1000000:3000000 script=%(EXPSCRIPT_SBNDCODE)s @@ -820,8 +820,8 @@ testlist=nucosmics_gen_quick_test_sbndcode nucosmics_g4_quick_test_sbndcode nuco STAGE_NAME=gen NEVENTS=%(NEVENTS_SEQ_NUCOSMICS_SBNDCODE)s # calibrated on sbndbuild01.fnal.gov on 20180305 -cpu_usage_range=600:900 -mem_usage_range=2500000:3500000 +cpu_usage_range=206:900 +mem_usage_range=1290400:3500000 script=%(EXPSCRIPT_SBNDCODE)s FHiCL_FILE=%(CI_FHICL_PREFIX_SBNDCODE)snucosmics_%(STAGE_NAME)s_seq_test_sbndcode.fcl @@ -841,8 +841,8 @@ STAGE_NAME=g4 INPUT_STAGE_NAME=gen NEVENTS=%(NEVENTS_SEQ_NUCOSMICS_SBNDCODE)s # calibrated on sbndbuild01.fnal.gov on 20180305 -cpu_usage_range=3500:4200 -mem_usage_range=4500000:5500000 +cpu_usage_range=1854:4200 +mem_usage_range=3473101:5500000 script=%(EXPSCRIPT_SBNDCODE)s requires=nucosmics_%(INPUT_STAGE_NAME)s_seq_test_sbndcode @@ -864,8 +864,8 @@ STAGE_NAME=detsim INPUT_STAGE_NAME=g4 NEVENTS=%(NEVENTS_SEQ_NUCOSMICS_SBNDCODE)s # calibrated on sbndbuild01.fnal.gov on 20180305 -cpu_usage_range=1100:1400 -mem_usage_range=3500000:4500000 +cpu_usage_range=1100:3809 +mem_usage_range=3500000:7083228 script=%(EXPSCRIPT_SBNDCODE)s requires=nucosmics_%(INPUT_STAGE_NAME)s_seq_test_sbndcode @@ -888,7 +888,7 @@ INPUT_STAGE_NAME=detsim NEVENTS=%(NEVENTS_SEQ_NUCOSMICS_SBNDCODE)s # calibrated on sbndbuild01.fnal.gov on 20180305 cpu_usage_range=600:800 -mem_usage_range=3000000:4000000 +mem_usage_range=1945911:4000000 script=%(EXPSCRIPT_SBNDCODE)s requires=nucosmics_%(INPUT_STAGE_NAME)s_seq_test_sbndcode @@ -910,8 +910,8 @@ STAGE_NAME=reco2 INPUT_STAGE_NAME=reco1 NEVENTS=%(NEVENTS_SEQ_NUCOSMICS_SBNDCODE)s # calibrated on sbndbuild01.fnal.gov on 20180305 -cpu_usage_range=2200:2500 -mem_usage_range=2500000:3500000 +cpu_usage_range=1342:2500 +mem_usage_range=2157647:3500000 script=%(EXPSCRIPT_SBNDCODE)s requires=nucosmics_%(INPUT_STAGE_NAME)s_seq_test_sbndcode @@ -1022,8 +1022,8 @@ output1=%(TFILENAME)s STAGE_NAME=reco1 INPUT_STAGE_NAME=decoders NEVENTS=2 -cpu_usage_range=500:1500 -mem_usage_range=1500000:3000000 +cpu_usage_range=500:2303 +mem_usage_range=1500000:7159462 script=%(EXPSCRIPT_SBNDCODE)s FHiCL_FILE=%(CI_FHICL_PREFIX_SBNDCODE)sdata_offBeamZeroBias_%(STAGE_NAME)s_quick_test_sbndcode.fcl @@ -1043,7 +1043,7 @@ STAGE_NAME=reco2 INPUT_STAGE_NAME=reco1 NEVENTS=2 cpu_usage_range=250:1000 -mem_usage_range=1000000:2000000 +mem_usage_range=1000000:2274627 script=%(EXPSCRIPT_SBNDCODE)s FHiCL_FILE=%(CI_FHICL_PREFIX_SBNDCODE)sdata_offBeamZeroBias_%(STAGE_NAME)s_quick_test_sbndcode.fcl @@ -1062,7 +1062,7 @@ output1=%(TFILENAME)s STAGE_NAME=caf INPUT_STAGE_NAME=reco2 NEVENTS=5 -cpu_usage_range=100:1000 +cpu_usage_range=74:1000 mem_usage_range=1000000:3000000 script=%(EXPSCRIPT_SBNDCODE)s @@ -1090,7 +1090,7 @@ testlist=data_offBeamZeroBias_decoders_quick_test_sbndcode data_offBeamZeroBias_ STAGE_NAME=decoders NEVENTS=%(NEVENTS_SEQ_DATA_SBNDCODE)s cpu_usage_range=10:102 -mem_usage_range=500000:700000 +mem_usage_range=500000:1262633 script=%(EXPSCRIPT_SBNDCODE)s @@ -1110,8 +1110,8 @@ output1=%(TFILENAME)s STAGE_NAME=reco1 INPUT_STAGE_NAME=decoders NEVENTS=%(NEVENTS_SEQ_DATA_SBNDCODE)s -cpu_usage_range=1200:1600 -mem_usage_range=3500000:4500000 +cpu_usage_range=1200:3465 +mem_usage_range=3500000:7417141 script=%(EXPSCRIPT_SBNDCODE)s requires=data_offBeamZeroBias_%(INPUT_STAGE_NAME)s_seq_test_sbndcode @@ -1132,8 +1132,8 @@ output1=%(TFILENAME)s STAGE_NAME=reco2 INPUT_STAGE_NAME=reco1 NEVENTS=%(NEVENTS_SEQ_DATA_SBNDCODE)s -cpu_usage_range=1200:1600 -mem_usage_range=3500000:4500000 +cpu_usage_range=711:1600 +mem_usage_range=2008524:4500000 script=%(EXPSCRIPT_SBNDCODE)s requires=data_offBeamZeroBias_%(INPUT_STAGE_NAME)s_seq_test_sbndcode @@ -1204,7 +1204,7 @@ testlist=compilation_test_sbndcode [test fcl_checks_sbndcode] cpu_usage_range=0:100 -mem_usage_range=10000:60000 +mem_usage_range=10000:66742 script=${SBNDCODE_DIR}/test/fcl_checks.sh STAGE_NAME=fcl EXTRA_DIR=%(FCLCHECK_INPUT_DIRNAME_SBNDCODE)s @@ -1214,7 +1214,7 @@ parse_art_output=False [test update_refs_fcl_checks_sbndcode] cpu_usage_range=0:100 -mem_usage_range=10000:50000 +mem_usage_range=10000:62189 script=${SBNDCODE_DIR}/test/fcl_checks.sh STAGE_NAME=fcl EXTRA_DIR=%(FCLCHECK_INPUT_DIRNAME_SBNDCODE)s From a1cccf88208f97d4e98ea94e0bd298232e863c1d Mon Sep 17 00:00:00 2001 From: nathanielerowe <70993723+nathanielerowe@users.noreply.github.com> Date: Fri, 13 Mar 2026 12:58:05 -0500 Subject: [PATCH 73/75] Update sbncode version to v10_20_03 --- ups/product_deps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ups/product_deps b/ups/product_deps index 29ba0e0fd..8b02783e4 100644 --- a/ups/product_deps +++ b/ups/product_deps @@ -253,7 +253,7 @@ wpdir product_dir wire-cell-cfg # #################################### product version qual flags -sbncode v10_15_00 - +sbncode v10_20_03 - cetmodules v3_24_01 - only_for_build sbnd_data v01_42_00 - sbndutil v10_06_01 - optional From 62fc4d532696353bc6eb83528899424670dcea54 Mon Sep 17 00:00:00 2001 From: Nathaniel Date: Mon, 16 Mar 2026 09:36:13 -0500 Subject: [PATCH 74/75] Update versioning --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f93a660ef..54621576a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ cmake_minimum_required(VERSION 3.20 FATAL_ERROR) -set(${PROJECT_NAME}_CMAKE_PROJECT_VERSION_STRING 10.14.02.02) +set(${PROJECT_NAME}_CMAKE_PROJECT_VERSION_STRING 10.20.03) find_package(cetmodules REQUIRED) project(sbndcode LANGUAGES CXX) From 229cb46ee2916f550dac1b08570b03c8ad961f5e Mon Sep 17 00:00:00 2001 From: Lynn Tung <71307529+lynnt20@users.noreply.github.com> Date: Tue, 14 Apr 2026 14:01:23 -0500 Subject: [PATCH 75/75] Remove LegacyLArG4 from MODULE_LIBRARIES --- sbndcode/Calorimetry/CMakeLists.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/sbndcode/Calorimetry/CMakeLists.txt b/sbndcode/Calorimetry/CMakeLists.txt index f674709d4..28452cab4 100644 --- a/sbndcode/Calorimetry/CMakeLists.txt +++ b/sbndcode/Calorimetry/CMakeLists.txt @@ -1,7 +1,6 @@ set (MODULE_LIBRARIES larsim::PhotonPropagation larsim::OpticalPath - larsim::LegacyLArG4 larcorealg::Geometry larcore::Geometry_Geometry_service larevt::CalibrationDBI_Providers