From a54b43ebe22b36c4c5dfeca999667963e2c97679 Mon Sep 17 00:00:00 2001 From: Anna Heggestuen Date: Mon, 2 Jun 2025 12:55:00 -0500 Subject: [PATCH 1/4] add PMTBeamSignal to sbnobj, define new helper functions in PMTBeamSignal.cxx --- sbnobj/Common/PMT/Data/CMakeLists.txt | 1 + sbnobj/Common/PMT/Data/PMTBeamSignal.cxx | 125 +++++++++++++++++++++++ sbnobj/Common/PMT/Data/PMTBeamSignal.hh | 92 +++++++++++++++++ sbnobj/Common/PMT/Data/classes.h | 1 + sbnobj/Common/PMT/Data/classes_def.xml | 5 +- 5 files changed, 223 insertions(+), 1 deletion(-) create mode 100644 sbnobj/Common/PMT/Data/PMTBeamSignal.cxx create mode 100644 sbnobj/Common/PMT/Data/PMTBeamSignal.hh diff --git a/sbnobj/Common/PMT/Data/CMakeLists.txt b/sbnobj/Common/PMT/Data/CMakeLists.txt index 6aa848ff..d970990c 100644 --- a/sbnobj/Common/PMT/Data/CMakeLists.txt +++ b/sbnobj/Common/PMT/Data/CMakeLists.txt @@ -1,5 +1,6 @@ cet_make_library( SOURCE + PMTBeamSignal.cxx PMTconfiguration.cxx V1730Configuration.cxx V1730channelConfiguration.cxx diff --git a/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx b/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx new file mode 100644 index 00000000..08530fa0 --- /dev/null +++ b/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx @@ -0,0 +1,125 @@ +/** + * @file sbnobj/Common/PMT/Data/PMTBeamSignal.cxx + * @brief Holds the event-by-event RWM or EW times + * @author Anna Heggestuen (aheggest@colostate.edu) + * @date May 19, 2025 + * @see sbnobj/Common/PMT/Data/PMTBeamSignal.h + */ + +//library header +#include "sbnobj/Common/PMT/Data/PMTBeamSignal.hh" + +// C/C++ standard libraries +#include + +// ----------------------------------------------------------------------------- +void sbn::timing::SelectFirstOpHitByTime(const recob::OpHit* const hit, + std::map &startmap, + std::map &risemap) +{ + const int ch = hit->OpChannel(); + double ts = hit->StartTime(); + double tr = hit->RiseTime(); + // select the first ophit (by time) in each channel + if (startmap.find(ch) != startmap.end()) + { + if (ts < startmap[ch]) + { + startmap[ch] = ts; + risemap[ch] = ts + tr; + } + } + else + { + startmap[ch] = ts; + risemap[ch] = ts + tr; + } +} +// ----------------------------------------------------------------------------- +int sbn::timing::getSideByChannel(const int channel) +{ + /* + Channels are numbered from east to west, from North (cryo side) to South (beam side) + We look in the opposide direction wrt to the beam direction South->North: + - Left is the east wall of each cryostat; + - Right is the west side of each cryostat; + - [ 0:89 ] and [180:269] are on the left, + the return value of the function is 0; + - [ 90-179 ] and [ 270:359 ] are on the right, + the return value of the function is 1; + */ + + int side = channel / 90; // always round down + return side % 2; +} + +// ----------------------------------------------------------------------------- +double sbn::timing::getFlashBunchTime(std::map startmap, + std::map risemap, + std::vector RWMTimes) +{ + // if no RWM info available, all pmt_start_time_rwm are invalid + // return icarus::timing::NoTime as well for the flash + if (RWMTimes.empty()) + return sbn::timing::NoTime; + + std::vector channels; + std::vector hit_rise_time_rwm; + for (auto it = startmap.begin(); it != startmap.end(); it++){ + int ch = it->first; + channels.push_back(ch); + auto rwm = RWMTimes.at(ch); + if (!rwm.isValid()){ + std::cout << "No RWM signal for channel " << ch << " " + << "(Crate " << rwm.crate << ", Board " << rwm.digitizerLabel + << ", SpecialChannel " << rwm.specialChannel << ")\n"; + } + float rwm_trigger = rwm.startTime; // rwm time w.r.t. trigger time [us] + hit_rise_time_rwm.push_back(risemap[ch] - rwm_trigger); + } + + double tfirst_left = std::numeric_limits::max(); + double tfirst_right = std::numeric_limits::max(); + + int nleft = 0; + int nright = 0; + for(std::size_t i = 0; i < hit_rise_time_rwm.size(); i++){ + int ch = channels[i]; + int side = sbn::timing::getSideByChannel(ch); + //int side = (ch / 90) % 2 ; //move this to a function as Matteo did to keep doc clear + double t = hit_rise_time_rwm[i]; // rise time w.r.t. rwm + + // if any RWM copy is missing (therefore missing for an entire PMT crate), + // it might not be possible to use the first hits (they might not have a RMW time) + // so return icarus::timing::NoTime as in other bad cases + if (!RWMTimes[i].isValid()) + return sbn::timing::NoTime; + + // count hits separetely on the two walls + if (side == 0) + { + nleft++; + if (t < tfirst_left) + tfirst_left = t; + } + else if (side == 1) + { + nright++; + if (t < tfirst_right) + tfirst_right = t; + } + } //end loop over m_hit_rise_time_rwm vector + + // if there are no hits in one of the walls... very rare? + if (nleft < 1 || nright < 1) + { + std::cout << "Flash doesn't have hits on both walls!" + << "Left: " << nleft << " t " << tfirst_left << " " + << "Right: " << nright << " t " << tfirst_right; + // return what we have... + return (tfirst_left < tfirst_right) ? tfirst_left : tfirst_right; + } + + return (tfirst_left + tfirst_right) / 2.; + +} diff --git a/sbnobj/Common/PMT/Data/PMTBeamSignal.hh b/sbnobj/Common/PMT/Data/PMTBeamSignal.hh new file mode 100644 index 00000000..89c385a5 --- /dev/null +++ b/sbnobj/Common/PMT/Data/PMTBeamSignal.hh @@ -0,0 +1,92 @@ +/** + * @file sbnobj/Common/PMT/Data/PMTBeamSignal.hh (moved from icaruscode/IcarusObj/PMTBeamSignal.h) + * @brief Holds the event-by-event RWM or EW times + * @author Matteo Vicenzi (mvicenzi@bnl.gov) + * @date March 14 2024, updated May 2025 + */ + +#ifndef SBNOBJ_COMMON_PMT_DATA_PMTBEAMSIGNAL_HH +#define SBNOBJ_COMMON_PMT_DATA_PMTBEAMSIGNAL_HH + +// LArSoft libraries +#include "lardataobj/RecoBase/OpHit.h" + +// C/C++ standard libraries +#include +#include +#include +#include +#include +#include //remove after testing + +namespace sbn::timing +{ + + /// Special value to denote no special channel information. + static constexpr auto NoChannel = std::numeric_limits::max(); + /// Special value to denote no time channel information. + static constexpr double NoTime = std::numeric_limits::max(); + // Special value to denote no sample information. + static constexpr std::size_t NoSample = 0; + + void SelectFirstOpHitByTime(const recob::OpHit* const hit, + std::map &startmap, + std::map &risemap); + + int getSideByChannel(const int channel); + // RWM times + //std::vector fRWMTimes; + //double getRWMRelativeTime(int channel, double t); + /*double getRWMRelativeTime(int channel, double t){ + std::cout << "channel, t = " << channel << ", " << t << "\n"; + return NoTime; + }*/ + + /** + * @brief Beam time as seen by a PMT readout board. + * + * This could either be an early warning (EW) or a resistive wall monitor (RWM) time. + * These signals are delivered via fibers and digitized in special PMT channels. + * + * Both the time in @ref DetectorClocksElectronicsTime "electronics time scale" + * and time time relative to the hardware trigger are included. + * + * The information in this object may be missing: its validity should + * always be checked in advance with `isValid()`. + */ + + struct PMTBeamSignal + { + + /// Special channel this time was extracted from. + /// These are defined in `CAEN_V1730_setup_icarus.fcl`. + unsigned int specialChannel = NoChannel; + + /// Board on which the special channel is on (e.g: WW-TOP-A). + /// Should match the same format as `icarusDB::PMTChannelInfo_t::digitizerLabel`. + std::string digitizerLabel = ""; + + /// Crate this time applies to (e.g.: WW-TOP). + /// Corresponds to the first part of `digitizerLabel`. + std::string crate = ""; + + /// Sample within the waveform where the reference signal is found. + std::size_t sample = NoSample; + + /// Start time in electronics time [us]. + double startTimeAbs = NoTime; + + /// Start time relative to trigger time [us]. + double startTime = NoTime; + + /// Returns whether the time is valid. + bool isValid() const { return (sample != NoSample); } + }; + + double getFlashBunchTime(std::map startmap, + std::map risemap, + std::vector RWMTimes); + +} // namespace sbn::timing + +#endif // SBNOBJ_COMMON_PMT_DATA_PMTBEAMSIGNAL_HH \ No newline at end of file diff --git a/sbnobj/Common/PMT/Data/classes.h b/sbnobj/Common/PMT/Data/classes.h index 183a3c78..8a8e6bb0 100644 --- a/sbnobj/Common/PMT/Data/classes.h +++ b/sbnobj/Common/PMT/Data/classes.h @@ -12,6 +12,7 @@ // SBN libraries #include "sbnobj/Common/PMT/Data/PMTconfiguration.h" +#include "sbnobj/Common/PMT/Data/PMTBeamSignal.hh" // framework libraries #include "canvas/Persistency/Common/Ptr.h" diff --git a/sbnobj/Common/PMT/Data/classes_def.xml b/sbnobj/Common/PMT/Data/classes_def.xml index 2afad393..c6f4a535 100644 --- a/sbnobj/Common/PMT/Data/classes_def.xml +++ b/sbnobj/Common/PMT/Data/classes_def.xml @@ -41,7 +41,10 @@ - + + + + From 480b822643f4cd0cdbc01a1f919a11d3ecf56246 Mon Sep 17 00:00:00 2001 From: Anna Heggestuen Date: Mon, 2 Jun 2025 13:12:19 -0500 Subject: [PATCH 2/4] move cout statements to MessageFacility output --- sbnobj/Common/PMT/Data/CMakeLists.txt | 3 ++- sbnobj/Common/PMT/Data/PMTBeamSignal.cxx | 9 ++++++--- sbnobj/Common/PMT/Data/PMTBeamSignal.hh | 7 ------- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/sbnobj/Common/PMT/Data/CMakeLists.txt b/sbnobj/Common/PMT/Data/CMakeLists.txt index d970990c..c62bc7ea 100644 --- a/sbnobj/Common/PMT/Data/CMakeLists.txt +++ b/sbnobj/Common/PMT/Data/CMakeLists.txt @@ -5,7 +5,8 @@ cet_make_library( V1730Configuration.cxx V1730channelConfiguration.cxx LIBRARIES - lardataobj::RawData + messagefacility::MF_MessageLogger + lardataobj::RawData ) art_dictionary(DICTIONARY_LIBRARIES sbnobj::Common_PMT_Data) diff --git a/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx b/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx index 08530fa0..d9ca2bff 100644 --- a/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx +++ b/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx @@ -1,7 +1,7 @@ /** * @file sbnobj/Common/PMT/Data/PMTBeamSignal.cxx * @brief Holds the event-by-event RWM or EW times - * @author Anna Heggestuen (aheggest@colostate.edu) + * @author Anna Heggestuen (aheggest@colostate.edu), adapted from M. Vincenzi in https://github.com/SBNSoftware/icaruscode/pull/751 * @date May 19, 2025 * @see sbnobj/Common/PMT/Data/PMTBeamSignal.h */ @@ -9,6 +9,9 @@ //library header #include "sbnobj/Common/PMT/Data/PMTBeamSignal.hh" +// framework libraries +#include "messagefacility/MessageLogger/MessageLogger.h" + // C/C++ standard libraries #include @@ -70,7 +73,7 @@ double sbn::timing::getFlashBunchTime(std::map startmap, channels.push_back(ch); auto rwm = RWMTimes.at(ch); if (!rwm.isValid()){ - std::cout << "No RWM signal for channel " << ch << " " + mf::LogTrace("PMTBeamSignal getFlashBunchTime") << "No RWM signal for channel " << ch << " " << "(Crate " << rwm.crate << ", Board " << rwm.digitizerLabel << ", SpecialChannel " << rwm.specialChannel << ")\n"; } @@ -113,7 +116,7 @@ double sbn::timing::getFlashBunchTime(std::map startmap, // if there are no hits in one of the walls... very rare? if (nleft < 1 || nright < 1) { - std::cout << "Flash doesn't have hits on both walls!" + mf::LogWarning("PMTBeamSignal getFlashBunchTime") << "Flash doesn't have hits on both walls!" << "Left: " << nleft << " t " << tfirst_left << " " << "Right: " << nright << " t " << tfirst_right; // return what we have... diff --git a/sbnobj/Common/PMT/Data/PMTBeamSignal.hh b/sbnobj/Common/PMT/Data/PMTBeamSignal.hh index 89c385a5..1b4f1ce6 100644 --- a/sbnobj/Common/PMT/Data/PMTBeamSignal.hh +++ b/sbnobj/Common/PMT/Data/PMTBeamSignal.hh @@ -34,13 +34,6 @@ namespace sbn::timing std::map &risemap); int getSideByChannel(const int channel); - // RWM times - //std::vector fRWMTimes; - //double getRWMRelativeTime(int channel, double t); - /*double getRWMRelativeTime(int channel, double t){ - std::cout << "channel, t = " << channel << ", " << t << "\n"; - return NoTime; - }*/ /** * @brief Beam time as seen by a PMT readout board. From 519bea6995d58bff59d07b7a171c842665bb3a51 Mon Sep 17 00:00:00 2001 From: Anna Heggestuen Date: Mon, 2 Jun 2025 16:14:40 -0500 Subject: [PATCH 3/4] remove startmap from getFlashBunchTime function definition as it is not needed --- sbnobj/Common/PMT/Data/PMTBeamSignal.cxx | 12 +++++------- sbnobj/Common/PMT/Data/PMTBeamSignal.hh | 4 +--- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx b/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx index d9ca2bff..2b279e5e 100644 --- a/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx +++ b/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx @@ -1,7 +1,7 @@ /** * @file sbnobj/Common/PMT/Data/PMTBeamSignal.cxx * @brief Holds the event-by-event RWM or EW times - * @author Anna Heggestuen (aheggest@colostate.edu), adapted from M. Vincenzi in https://github.com/SBNSoftware/icaruscode/pull/751 + * @author Anna Heggestuen (aheggest@colostate.edu), adapted from M. Vicenzi in https://github.com/SBNSoftware/icaruscode/pull/751 * @date May 19, 2025 * @see sbnobj/Common/PMT/Data/PMTBeamSignal.h */ @@ -12,8 +12,6 @@ // framework libraries #include "messagefacility/MessageLogger/MessageLogger.h" -// C/C++ standard libraries -#include // ----------------------------------------------------------------------------- void sbn::timing::SelectFirstOpHitByTime(const recob::OpHit* const hit, @@ -57,8 +55,7 @@ int sbn::timing::getSideByChannel(const int channel) } // ----------------------------------------------------------------------------- -double sbn::timing::getFlashBunchTime(std::map startmap, - std::map risemap, +double sbn::timing::getFlashBunchTime(std::map risemap, std::vector RWMTimes) { // if no RWM info available, all pmt_start_time_rwm are invalid @@ -68,7 +65,7 @@ double sbn::timing::getFlashBunchTime(std::map startmap, std::vector channels; std::vector hit_rise_time_rwm; - for (auto it = startmap.begin(); it != startmap.end(); it++){ + for (auto it = risemap.begin(); it != risemap.end(); it++){ int ch = it->first; channels.push_back(ch); auto rwm = RWMTimes.at(ch); @@ -78,7 +75,8 @@ double sbn::timing::getFlashBunchTime(std::map startmap, << ", SpecialChannel " << rwm.specialChannel << ")\n"; } float rwm_trigger = rwm.startTime; // rwm time w.r.t. trigger time [us] - hit_rise_time_rwm.push_back(risemap[ch] - rwm_trigger); + float firstHitRisetime_trigger = it->second; // first opHit rise time w.r.t. trigger time [us] + hit_rise_time_rwm.push_back(firstHitRisetime_trigger - rwm_trigger); } double tfirst_left = std::numeric_limits::max(); diff --git a/sbnobj/Common/PMT/Data/PMTBeamSignal.hh b/sbnobj/Common/PMT/Data/PMTBeamSignal.hh index 1b4f1ce6..7e28a9b0 100644 --- a/sbnobj/Common/PMT/Data/PMTBeamSignal.hh +++ b/sbnobj/Common/PMT/Data/PMTBeamSignal.hh @@ -17,7 +17,6 @@ #include #include #include -#include //remove after testing namespace sbn::timing { @@ -76,8 +75,7 @@ namespace sbn::timing bool isValid() const { return (sample != NoSample); } }; - double getFlashBunchTime(std::map startmap, - std::map risemap, + double getFlashBunchTime(std::map risemap, std::vector RWMTimes); } // namespace sbn::timing From 92578e75e67614cf3291c97f416f340a7a717e53 Mon Sep 17 00:00:00 2001 From: Anna Heggestuen Date: Thu, 5 Jun 2025 14:04:37 -0500 Subject: [PATCH 4/4] remove startmap from SelectFirstOpHitByTime function as its not needed --- sbnobj/Common/PMT/Data/PMTBeamSignal.cxx | 16 ++++++---------- sbnobj/Common/PMT/Data/PMTBeamSignal.hh | 5 ++--- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx b/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx index 2b279e5e..20f7e819 100644 --- a/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx +++ b/sbnobj/Common/PMT/Data/PMTBeamSignal.cxx @@ -15,26 +15,23 @@ // ----------------------------------------------------------------------------- void sbn::timing::SelectFirstOpHitByTime(const recob::OpHit* const hit, - std::map &startmap, std::map &risemap) { const int ch = hit->OpChannel(); double ts = hit->StartTime(); double tr = hit->RiseTime(); // select the first ophit (by time) in each channel - if (startmap.find(ch) != startmap.end()) + if (risemap.find(ch) != risemap.end()) { - if (ts < startmap[ch]) - { - startmap[ch] = ts; - risemap[ch] = ts + tr; - } + if (tr < risemap[ch]) + { + risemap[ch] = ts + tr; + } } else { - startmap[ch] = ts; risemap[ch] = ts + tr; - } + } } // ----------------------------------------------------------------------------- int sbn::timing::getSideByChannel(const int channel) @@ -87,7 +84,6 @@ double sbn::timing::getFlashBunchTime(std::map risemap, for(std::size_t i = 0; i < hit_rise_time_rwm.size(); i++){ int ch = channels[i]; int side = sbn::timing::getSideByChannel(ch); - //int side = (ch / 90) % 2 ; //move this to a function as Matteo did to keep doc clear double t = hit_rise_time_rwm[i]; // rise time w.r.t. rwm // if any RWM copy is missing (therefore missing for an entire PMT crate), diff --git a/sbnobj/Common/PMT/Data/PMTBeamSignal.hh b/sbnobj/Common/PMT/Data/PMTBeamSignal.hh index 7e28a9b0..cfe471db 100644 --- a/sbnobj/Common/PMT/Data/PMTBeamSignal.hh +++ b/sbnobj/Common/PMT/Data/PMTBeamSignal.hh @@ -1,7 +1,7 @@ /** - * @file sbnobj/Common/PMT/Data/PMTBeamSignal.hh (moved from icaruscode/IcarusObj/PMTBeamSignal.h) + * @file sbnobj/Common/PMT/Data/PMTBeamSignal.hh (moved from icaruscode/IcarusObj/Legacy/PMTBeamSignal.h) * @brief Holds the event-by-event RWM or EW times - * @author Matteo Vicenzi (mvicenzi@bnl.gov) + * @author Matteo Vicenzi (mvicenzi@bnl.gov), Anna Heggestuen (aheggest@colostate.edu) * @date March 14 2024, updated May 2025 */ @@ -29,7 +29,6 @@ namespace sbn::timing static constexpr std::size_t NoSample = 0; void SelectFirstOpHitByTime(const recob::OpHit* const hit, - std::map &startmap, std::map &risemap); int getSideByChannel(const int channel);