Skip to content

Commit 2182720

Browse files
authored
Merge pull request #130 from SBNSoftware/feature/aheggest_RWMinCAF
Move PMTBeamSignal data product from icaruscode to sbnobj
2 parents 722c2fc + 05b33df commit 2182720

5 files changed

Lines changed: 212 additions & 2 deletions

File tree

sbnobj/Common/PMT/Data/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
cet_make_library(
22
SOURCE
3+
PMTBeamSignal.cxx
34
PMTconfiguration.cxx
45
V1730Configuration.cxx
56
V1730channelConfiguration.cxx
67
LIBRARIES
7-
lardataobj::RawData
8+
messagefacility::MF_MessageLogger
9+
lardataobj::RawData
810
)
911

1012
art_dictionary(DICTIONARY_LIBRARIES sbnobj::Common_PMT_Data)
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/**
2+
* @file sbnobj/Common/PMT/Data/PMTBeamSignal.cxx
3+
* @brief Holds the event-by-event RWM or EW times
4+
* @author Anna Heggestuen (aheggest@colostate.edu), adapted from M. Vicenzi in https://github.com/SBNSoftware/icaruscode/pull/751
5+
* @date May 19, 2025
6+
* @see sbnobj/Common/PMT/Data/PMTBeamSignal.h
7+
*/
8+
9+
//library header
10+
#include "sbnobj/Common/PMT/Data/PMTBeamSignal.hh"
11+
12+
// framework libraries
13+
#include "messagefacility/MessageLogger/MessageLogger.h"
14+
15+
16+
// -----------------------------------------------------------------------------
17+
void sbn::timing::SelectFirstOpHitByTime(const recob::OpHit* const hit,
18+
std::map<int, double> &risemap)
19+
{
20+
const int ch = hit->OpChannel();
21+
double ts = hit->StartTime();
22+
double tr = hit->RiseTime();
23+
// select the first ophit (by time) in each channel
24+
if (risemap.find(ch) != risemap.end())
25+
{
26+
if (tr < risemap[ch])
27+
{
28+
risemap[ch] = ts + tr;
29+
}
30+
}
31+
else
32+
{
33+
risemap[ch] = ts + tr;
34+
}
35+
}
36+
// -----------------------------------------------------------------------------
37+
int sbn::timing::getSideByChannel(const int channel)
38+
{
39+
/*
40+
Channels are numbered from east to west, from North (cryo side) to South (beam side)
41+
We look in the opposide direction wrt to the beam direction South->North:
42+
- Left is the east wall of each cryostat;
43+
- Right is the west side of each cryostat;
44+
- [ 0:89 ] and [180:269] are on the left,
45+
the return value of the function is 0;
46+
- [ 90-179 ] and [ 270:359 ] are on the right,
47+
the return value of the function is 1;
48+
*/
49+
50+
int side = channel / 90; // always round down
51+
return side % 2;
52+
}
53+
54+
// -----------------------------------------------------------------------------
55+
double sbn::timing::getFlashBunchTime(std::map<int, double> risemap,
56+
std::vector<sbn::timing::PMTBeamSignal> RWMTimes)
57+
{
58+
// if no RWM info available, all pmt_start_time_rwm are invalid
59+
// return icarus::timing::NoTime as well for the flash
60+
if (RWMTimes.empty())
61+
return sbn::timing::NoTime;
62+
63+
std::vector<int> channels;
64+
std::vector<double> hit_rise_time_rwm;
65+
for (auto it = risemap.begin(); it != risemap.end(); it++){
66+
int ch = it->first;
67+
channels.push_back(ch);
68+
auto rwm = RWMTimes.at(ch);
69+
if (!rwm.isValid()){
70+
mf::LogTrace("PMTBeamSignal getFlashBunchTime") << "No RWM signal for channel " << ch << " "
71+
<< "(Crate " << rwm.crate << ", Board " << rwm.digitizerLabel
72+
<< ", SpecialChannel " << rwm.specialChannel << ")\n";
73+
}
74+
float rwm_trigger = rwm.startTime; // rwm time w.r.t. trigger time [us]
75+
float firstHitRisetime_trigger = it->second; // first opHit rise time w.r.t. trigger time [us]
76+
hit_rise_time_rwm.push_back(firstHitRisetime_trigger - rwm_trigger);
77+
}
78+
79+
double tfirst_left = std::numeric_limits<double>::max();
80+
double tfirst_right = std::numeric_limits<double>::max();
81+
82+
int nleft = 0;
83+
int nright = 0;
84+
for(std::size_t i = 0; i < hit_rise_time_rwm.size(); i++){
85+
int ch = channels[i];
86+
int side = sbn::timing::getSideByChannel(ch);
87+
double t = hit_rise_time_rwm[i]; // rise time w.r.t. rwm
88+
89+
// if any RWM copy is missing (therefore missing for an entire PMT crate),
90+
// it might not be possible to use the first hits (they might not have a RMW time)
91+
// so return icarus::timing::NoTime as in other bad cases
92+
if (!RWMTimes[i].isValid())
93+
return sbn::timing::NoTime;
94+
95+
// count hits separetely on the two walls
96+
if (side == 0)
97+
{
98+
nleft++;
99+
if (t < tfirst_left)
100+
tfirst_left = t;
101+
}
102+
else if (side == 1)
103+
{
104+
nright++;
105+
if (t < tfirst_right)
106+
tfirst_right = t;
107+
}
108+
} //end loop over m_hit_rise_time_rwm vector
109+
110+
// if there are no hits in one of the walls... very rare?
111+
if (nleft < 1 || nright < 1)
112+
{
113+
mf::LogWarning("PMTBeamSignal getFlashBunchTime") << "Flash doesn't have hits on both walls!"
114+
<< "Left: " << nleft << " t " << tfirst_left << " "
115+
<< "Right: " << nright << " t " << tfirst_right;
116+
// return what we have...
117+
return (tfirst_left < tfirst_right) ? tfirst_left : tfirst_right;
118+
}
119+
120+
return (tfirst_left + tfirst_right) / 2.;
121+
122+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/**
2+
* @file sbnobj/Common/PMT/Data/PMTBeamSignal.hh (moved from icaruscode/IcarusObj/Legacy/PMTBeamSignal.h)
3+
* @brief Holds the event-by-event RWM or EW times
4+
* @author Matteo Vicenzi (mvicenzi@bnl.gov), Anna Heggestuen (aheggest@colostate.edu)
5+
* @date March 14 2024, updated May 2025
6+
*/
7+
8+
#ifndef SBNOBJ_COMMON_PMT_DATA_PMTBEAMSIGNAL_HH
9+
#define SBNOBJ_COMMON_PMT_DATA_PMTBEAMSIGNAL_HH
10+
11+
// LArSoft libraries
12+
#include "lardataobj/RecoBase/OpHit.h"
13+
14+
// C/C++ standard libraries
15+
#include <limits>
16+
#include <string>
17+
#include <vector>
18+
#include <map>
19+
#include <cstddef>
20+
21+
namespace sbn::timing
22+
{
23+
24+
/// Special value to denote no special channel information.
25+
static constexpr auto NoChannel = std::numeric_limits<unsigned int>::max();
26+
/// Special value to denote no time channel information.
27+
static constexpr double NoTime = std::numeric_limits<double>::max();
28+
// Special value to denote no sample information.
29+
static constexpr std::size_t NoSample = 0;
30+
31+
void SelectFirstOpHitByTime(const recob::OpHit* const hit,
32+
std::map<int, double> &risemap);
33+
34+
int getSideByChannel(const int channel);
35+
36+
/**
37+
* @brief Beam time as seen by a PMT readout board.
38+
*
39+
* This could either be an early warning (EW) or a resistive wall monitor (RWM) time.
40+
* These signals are delivered via fibers and digitized in special PMT channels.
41+
*
42+
* Both the time in @ref DetectorClocksElectronicsTime "electronics time scale"
43+
* and time time relative to the hardware trigger are included.
44+
*
45+
* The information in this object may be missing: its validity should
46+
* always be checked in advance with `isValid()`.
47+
*/
48+
49+
struct PMTBeamSignal
50+
{
51+
52+
/// Special channel this time was extracted from.
53+
/// These are defined in `CAEN_V1730_setup_icarus.fcl`.
54+
unsigned int specialChannel = NoChannel;
55+
56+
/// Board on which the special channel is on (e.g: WW-TOP-A).
57+
/// Should match the same format as `icarusDB::PMTChannelInfo_t::digitizerLabel`.
58+
std::string digitizerLabel = "";
59+
60+
/// Crate this time applies to (e.g.: WW-TOP).
61+
/// Corresponds to the first part of `digitizerLabel`.
62+
std::string crate = "";
63+
64+
/// Sample within the waveform where the reference signal is found.
65+
std::size_t sample = NoSample;
66+
67+
/// Start time in electronics time [us].
68+
double startTimeAbs = NoTime;
69+
70+
/// Start time relative to trigger time [us].
71+
double startTime = NoTime;
72+
73+
/// Returns whether the time is valid.
74+
bool isValid() const { return (sample != NoSample); }
75+
};
76+
77+
double getFlashBunchTime(std::map<int, double> risemap,
78+
std::vector<PMTBeamSignal> RWMTimes);
79+
80+
} // namespace sbn::timing
81+
82+
#endif // SBNOBJ_COMMON_PMT_DATA_PMTBEAMSIGNAL_HH

sbnobj/Common/PMT/Data/classes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
// SBN libraries
1414
#include "sbnobj/Common/PMT/Data/PMTconfiguration.h"
15+
#include "sbnobj/Common/PMT/Data/PMTBeamSignal.hh"
1516

1617
// framework libraries
1718
#include "canvas/Persistency/Common/Ptr.h"

sbnobj/Common/PMT/Data/classes_def.xml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,10 @@
4141
<class name="art::Ptr<sbn::PMTconfiguration>"/>
4242
<class name="art::Wrapper<sbn::PMTconfiguration>"/>
4343

44-
44+
<!-- PMTBeamSignal classes -->
45+
<class name ="art::Wrapper<vector<sbn::timing::PMTBeamSignal> >"/>
46+
<class name ="sbn::timing::PMTBeamSignal"/>
47+
<class name ="vector<sbn::timing::PMTBeamSignal>"/>
4548
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
4649
<!-- copy&paste templates for: -->
4750
<!-- PROD -->

0 commit comments

Comments
 (0)