All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sbndcode/sbndcode/CRT/CRTUtils/CRTHitRecoAlg.cc
Go to the documentation of this file.
1 #include "CRTHitRecoAlg.h"
2 
4 
5 namespace sbnd{
6 
7 CRTHitRecoAlg::CRTHitRecoAlg(const Config& config, double g4RefTime){
8 
9  this->reconfigure(config);
10 
11  if (fUseG4RefTimeOffset) {
13  }
14 }
15 
16 
18 }
19 
20 
22 
23 }
24 
25 
26 void CRTHitRecoAlg::reconfigure(const Config& config){
27 
29  fQPed = config.QPed();
30  fQSlope = config.QSlope();
31  fNpeScaleShift = config.NpeScaleShift();
33  fClockSpeedCRT = config.ClockSpeedCRT();
34  fTimeOffset = config.TimeOffset();
36  fPropDelay = config.PropDelay();
37  fTDelayNorm = config.TDelayNorm();
38  fTDelayShift = config.TDelayShift();
39  fTDelaySigma = config.TDelaySigma();
40  fTDelayOffset = config.TDelayOffset();
41 
42  return;
43 }
44 
45 std::map<std::pair<std::string, unsigned>, std::vector<CRTStrip>> CRTHitRecoAlg::CreateTaggerStrips(detinfo::DetectorClocksData const& clockData,
47  std::vector<art::Ptr<sbnd::crt::CRTData>> crtList){
48 
49  double readoutWindowMuS = clockData.TPCTick2Time((double)detProp.ReadOutWindowSize()); // [us]
50  double driftTimeMuS = fTpcGeo.MaxX()/detProp.DriftVelocity(); // [us]
51 
52  std::map<std::pair<std::string, unsigned>, std::vector<CRTStrip>> taggerStrips;
53 
54  for (size_t i = 0; i < crtList.size(); i+=2){
55 
56  // Get the time
57  //fTrigClock.SetTime(crtList[i]->T1());
58  //double t1 = fTrigClock.Time(); // [us]
59  double t1 = (double)(int)crtList[i]->T1()/fClockSpeedCRT; // [tick -> us]
61  if(!(t1 >= -driftTimeMuS && t1 <= readoutWindowMuS)) continue;
62  }
63 
64  CRTStrip strip = CreateCRTStrip(crtList[i], crtList[i+1], i);
65 
66  taggerStrips[strip.tagger].push_back(strip);
67 
68  }
69 
70  return taggerStrips;
71 
72 }
73 
74 
75 CRTStrip CRTHitRecoAlg::CreateCRTStrip(art::Ptr<sbnd::crt::CRTData> sipm1, art::Ptr<sbnd::crt::CRTData> sipm2, size_t ind){
76 
77  // Get the time, channel, center and width
78  //fTrigClock.SetTime(sipm1->T1());
79  //double t1 = fTrigClock.Time(); // [us]
80  double t1 = (double)(int)sipm1->T1()/fClockSpeedCRT; // [tick -> us]
81 
82  // Get strip info from the geometry service
83  uint32_t channel = sipm1->Channel();
84 
85  std::pair<std::string,unsigned> tagger = ChannelToTagger(channel);
86 
87  // Get the time of hit on the second SiPM
88  //fTrigClock.SetTime(sipm2->T1());
89  //double t2 = fTrigClock.Time(); // [us]
90  double t2 = (double)(int)sipm2->T1()/fClockSpeedCRT; // [tick -> us]
91 
92  // Calculate the number of photoelectrons at each SiPM
93  double npe1 = ((double)sipm1->ADC() - fQPed)/fQSlope;
94  double npe2 = ((double)sipm2->ADC() - fQPed)/fQSlope;
95 
96  // Calculate the distance between the SiPMs
97  std::pair<double, double> sipmDist = DistanceBetweenSipms(sipm1, sipm2);
98 
99  double time = (t1 + t2)/2.;
100 
101  CRTStrip stripHit = {time, channel, sipmDist.first, sipmDist.second, npe1+npe2, tagger, ind};
102  return stripHit;
103 
104 }
105 
106 std::pair<double, double> CRTHitRecoAlg::DistanceBetweenSipms(art::Ptr<sbnd::crt::CRTData> sipm1, art::Ptr<sbnd::crt::CRTData> sipm2){
107 
108  uint32_t channel = sipm1->Channel();
109  std::string stripName = fCrtGeo.ChannelToStripName(channel);
110  if (stripName.empty()) {
111  throw cet::exception("CRTHitRecoAlg")
112  << "Cannot find strip name for channel " << channel << std::endl;
113  }
114 
115  double width = fCrtGeo.GetStrip(stripName).width;
116 
117  // Calculate the number of photoelectrons at each SiPM
118  double npe1 = ((double)sipm1->ADC() - fQPed)/fQSlope;
119  double npe2 = ((double)sipm2->ADC() - fQPed)/fQSlope;
120 
121  // Calculate the distance between the SiPMs
122  double x = (width/2.)*atan(log(1.*npe2/npe1)) + (width/2.);
123 
124  // Calculate the error
125  double normx = x + 0.344677*x - 1.92045;
126  double ex = 1.92380e+00+1.47186e-02*normx-5.29446e-03*normx*normx;
127 
128  return std::make_pair(x, ex);
129 
130 }
131 
132 
133 std::vector<std::pair<sbn::crt::CRTHit, std::vector<int>>> CRTHitRecoAlg::CreateCRTHits(std::map<std::pair<std::string, unsigned>, std::vector<CRTStrip>> taggerStrips){
134 
135  std::vector<std::pair<sbn::crt::CRTHit, std::vector<int>>> returnHits;
136 
137  std::vector<uint8_t> tfeb_id = {0};
138  std::map<uint8_t, std::vector<std::pair<int,float>>> tpesmap;
139  tpesmap[0] = {std::make_pair(0,0)};
140 
141  // Remove any duplicate (same channel and time) hit strips
142  for(auto &tagStrip : taggerStrips){
143  std::sort(tagStrip.second.begin(), tagStrip.second.end(),
144  [](const CRTStrip & a, const CRTStrip & b) -> bool{
145  return (a.t0 < b.t0) ||
146  ((a.t0 == b.t0) && (a.channel < b.channel));
147  });
148  // Remove hits with the same time and channel
149  tagStrip.second.erase(std::unique(tagStrip.second.begin(), tagStrip.second.end(),
150  [](const CRTStrip & a, const CRTStrip & b) -> bool{
151  return a.t0 == b.t0 && a.channel == b.channel;
152  }), tagStrip.second.end());
153  }
154 
155  std::vector<std::string> usedTaggers;
156 
157  for (auto &tagStrip : taggerStrips){
158  if (std::find(usedTaggers.begin(),usedTaggers.end(),tagStrip.first.first)!=usedTaggers.end()) continue;
159  usedTaggers.push_back(tagStrip.first.first);
160  unsigned planeID = 0;
161  if(tagStrip.first.second==0) planeID = 1;
162  std::pair<std::string,unsigned> otherPlane = std::make_pair(tagStrip.first.first, planeID);
163 
164  for (size_t hit_i = 0; hit_i < tagStrip.second.size(); hit_i++){
165  // Get the position (in real space) of the 4 corners of the hit, taking charge sharing into account
166  std::vector<double> limits1 = ChannelToLimits(tagStrip.second[hit_i]);
167 
168  // Check for overlaps on the first plane
169  if(CheckModuleOverlap(tagStrip.second[hit_i].channel)){
170 
171  // Loop over all the hits on the parallel (odd) plane
172  for (size_t hit_j = 0; hit_j < taggerStrips[otherPlane].size(); hit_j++){
173  // Get the limits in the two variable directions
174  std::vector<double> limits2 = ChannelToLimits(taggerStrips[otherPlane][hit_j]);
175 
176  // If the time and position match then record the pair of hits
177  std::vector<double> overlap = CrtOverlap(limits1, limits2);
178  double t0_1 = tagStrip.second[hit_i].t0;
179  double t0_2 = taggerStrips[otherPlane][hit_j].t0;
180  if (overlap[0] != -99999 && std::abs(t0_1 - t0_2) < fTimeCoincidenceLimit){
181  // Calculate the mean and error in x, y, z
182  TVector3 mean((overlap[0] + overlap[1])/2.,
183  (overlap[2] + overlap[3])/2.,
184  (overlap[4] + overlap[5])/2.);
185  TVector3 error(std::abs((overlap[1] - overlap[0])/2.),
186  std::abs((overlap[3] - overlap[2])/2.),
187  std::abs((overlap[5] - overlap[4])/2.));
188 
189  // Correct and average the time
190  double time = CorrectTime(tagStrip.second[hit_i], taggerStrips[otherPlane][hit_j], mean) - fTimeOffset;
191  //double pes = tagStrip.second[hit_i].pes + taggerStrips[otherPlane][hit_j].pes;
192  double pes = CorrectNpe(tagStrip.second[hit_i], taggerStrips[otherPlane][hit_j], mean);
193  int plane = sbnd::CRTCommonUtils::GetPlaneIndex(tagStrip.first.first);
194 
195  // Create a CRT hit
196  sbn::crt::CRTHit crtHit = FillCrtHit(tfeb_id, tpesmap, pes, time, plane, mean.X(), error.X(),
197  mean.Y(), error.Y(), mean.Z(), error.Z(), tagStrip.first.first);
198  std::vector<int> dataIds;
199  dataIds.push_back(tagStrip.second[hit_i].dataID);
200  dataIds.push_back(tagStrip.second[hit_i].dataID+1);
201  dataIds.push_back(taggerStrips[otherPlane][hit_j].dataID);
202  dataIds.push_back(taggerStrips[otherPlane][hit_j].dataID+1);
203  returnHits.push_back(std::make_pair(crtHit, dataIds));
204  }
205 
206  }
207 
208  }
209  // If module doesn't overlap with a perpendicular one create 1D hits
210  else{
211  TVector3 mean((limits1[0] + limits1[1])/2.,
212  (limits1[2] + limits1[3])/2.,
213  (limits1[4] + limits1[5])/2.);
214  TVector3 error(std::abs((limits1[1] - limits1[0])/2.),
215  std::abs((limits1[3] - limits1[2])/2.),
216  std::abs((limits1[5] - limits1[4])/2.));
217 
218  double time = tagStrip.second[hit_i].t0 - fTimeOffset;
219  double pes = tagStrip.second[hit_i].pes;
220  int plane = sbnd::CRTCommonUtils::GetPlaneIndex(tagStrip.first.first);
221 
222  // Just use the single plane limits as the crt hit
223  sbn::crt::CRTHit crtHit = FillCrtHit(tfeb_id, tpesmap, pes, time, plane, mean.X(), error.X(),
224  mean.Y(), error.Y(), mean.Z(), error.Z(), tagStrip.first.first);
225  std::vector<int> dataIds;
226  dataIds.push_back(tagStrip.second[hit_i].dataID);
227  dataIds.push_back(tagStrip.second[hit_i].dataID+1);
228  returnHits.push_back(std::make_pair(crtHit, dataIds));
229  }
230 
231  }
232  // Loop over tagger modules on the perpendicular plane to look for 1D hits
233  for (size_t hit_j = 0; hit_j < taggerStrips[otherPlane].size(); hit_j++){
234  // Get the limits in the two variable directions
235  std::vector<double> limits1 = ChannelToLimits(taggerStrips[otherPlane][hit_j]);
236 
237  // Check if module overlaps with a perpendicular one
238  if(!CheckModuleOverlap(taggerStrips[otherPlane][hit_j].channel)){
239  TVector3 mean((limits1[0] + limits1[1])/2.,
240  (limits1[2] + limits1[3])/2.,
241  (limits1[4] + limits1[5])/2.);
242  TVector3 error(std::abs((limits1[1] - limits1[0])/2.),
243  std::abs((limits1[3] - limits1[2])/2.),
244  std::abs((limits1[5] - limits1[4])/2.));
245 
246  double time = taggerStrips[otherPlane][hit_j].t0 - fTimeOffset;
247  double pes = taggerStrips[otherPlane][hit_j].pes;
248  int plane = sbnd::CRTCommonUtils::GetPlaneIndex(otherPlane.first);
249 
250  // Just use the single plane limits as the crt hit
251  sbn::crt::CRTHit crtHit = FillCrtHit(tfeb_id, tpesmap, pes, time, plane, mean.X(), error.X(),
252  mean.Y(), error.Y(), mean.Z(), error.Z(), otherPlane.first);
253  std::vector<int> dataIds;
254  dataIds.push_back(taggerStrips[otherPlane][hit_j].dataID);
255  dataIds.push_back(taggerStrips[otherPlane][hit_j].dataID+1);
256  returnHits.push_back(std::make_pair(crtHit, dataIds));
257  }
258 
259  }
260 
261  }
262 
263  return returnHits;
264 
265 }
266 
267 
268 // Function to calculate the strip position limits in real space from channel
269 std::vector<double> CRTHitRecoAlg::ChannelToLimits(CRTStrip stripHit){
270 
271  std::string stripName = fCrtGeo.ChannelToStripName(stripHit.channel);
272  return fCrtGeo.StripLimitsWithChargeSharing(stripName, stripHit.x, stripHit.ex);
273 
274 } // CRTHitRecoAlg::ChannelToLimits()
275 
276 
277 // Function to calculate the overlap between two crt strips
278 std::vector<double> CRTHitRecoAlg::CrtOverlap(std::vector<double> strip1, std::vector<double> strip2){
279 
280  // Get the minimum and maximum X, Y, Z coordinates
281  double minX = std::max(strip1[0], strip2[0]);
282  double maxX = std::min(strip1[1], strip2[1]);
283  double minY = std::max(strip1[2], strip2[2]);
284  double maxY = std::min(strip1[3], strip2[3]);
285  double minZ = std::max(strip1[4], strip2[4]);
286  double maxZ = std::min(strip1[5], strip2[5]);
287 
288  std::vector<double> null = {-99999, -99999, -99999, -99999, -99999, -99999};
289  std::vector<double> overlap = {minX, maxX, minY, maxY, minZ, maxZ};
290 
291  // If the two strips overlap in 2 dimensions then return the overlap
292  if ((minX<maxX && minY<maxY) || (minX<maxX && minZ<maxZ) || (minY<maxY && minZ<maxZ)) return overlap;
293  // Otherwise return a "null" value
294  return null;
295 
296 } // CRTHitRecoAlg::CRTOverlap()
297 
298 
299 // Function to return the CRT tagger name and module position from the channel ID
300 std::pair<std::string,unsigned> CRTHitRecoAlg::ChannelToTagger(uint32_t channel){
301 
302  std::string stripName = fCrtGeo.ChannelToStripName(channel);
303  size_t planeID = fCrtGeo.GetModule(fCrtGeo.GetStrip(stripName).module).planeID;
304  std::string tagName = fCrtGeo.GetModule(fCrtGeo.GetStrip(stripName).module).tagger;
305 
306  std::pair<std::string, unsigned> output = std::make_pair(tagName, planeID);
307 
308  return output;
309 
310 } // CRTHitRecoAlg::ChannelToTagger()
311 
312 
313 // Function to check if a CRT strip overlaps with a perpendicular module
314 bool CRTHitRecoAlg::CheckModuleOverlap(uint32_t channel){
315 
316  std::string stripName = fCrtGeo.ChannelToStripName(channel);
317  return fCrtGeo.StripHasOverlap(stripName);
318 
319 } // CRTHitRecoAlg::CheckModuleOverlap
320 
321 
322 // Function to make filling a CRTHit a bit faster
323 sbn::crt::CRTHit CRTHitRecoAlg::FillCrtHit(std::vector<uint8_t> tfeb_id, std::map<uint8_t,
324  std::vector<std::pair<int,float>>> tpesmap, float peshit, double time, int plane,
325  double x, double ex, double y, double ey, double z, double ez, std::string tagger){
326 
327  sbn::crt::CRTHit crtHit;
328 
329  crtHit.feb_id = tfeb_id;
330  crtHit.pesmap = tpesmap;
331  crtHit.peshit = peshit;
332  crtHit.ts0_s_corr = 0;
333  crtHit.ts0_ns = time * 1e3;
334  crtHit.ts0_ns_corr = 0;
335  crtHit.ts1_ns = time * 1e3;
336  crtHit.ts0_s = time * 1e-6;
337  crtHit.plane = plane;
338  crtHit.x_pos = x;
339  crtHit.x_err = ex;
340  crtHit.y_pos = y;
341  crtHit.y_err = ey;
342  crtHit.z_pos = z;
343  crtHit.z_err = ez;
344  crtHit.tagger = tagger;
345 
346  mf::LogInfo("CRTHitRecoAlg") << "Filling hit with time " << time << ", fTimeOffset " << fTimeOffset << '\n'
347  << "\t and is in fact " << crtHit.ts0_ns << " " << crtHit.ts0_s << " " <<crtHit.ts1_ns << std::endl;
348 
349  return crtHit;
350 
351 } // CRTHitRecoAlg::FillCrtHit()
352 
353 
354 // Function to correct number of photoelectrons by distance down strip
355 double CRTHitRecoAlg::CorrectNpe(CRTStrip strip1, CRTStrip strip2, TVector3 position){
356  geo::Point_t pos {position.X(), position.Y(), position.Z()};
357 
358  // Get the strip name from the channel ID
359  std::string name1 = fCrtGeo.ChannelToStripName(strip1.channel);
360  std::string name2 = fCrtGeo.ChannelToStripName(strip2.channel);
361 
362  // Get the distance from the CRT hit to the sipm end
363  double stripDist1 = fCrtGeo.DistanceDownStrip(pos, name1);
364  double stripDist2 = fCrtGeo.DistanceDownStrip(pos, name2);
365 
366  // Correct the measured pe
367  double pesCorr1 = strip1.pes * pow(stripDist1 - fNpeScaleShift, 2) / pow(fNpeScaleShift, 2);
368  double pesCorr2 = strip2.pes * pow(stripDist2 - fNpeScaleShift, 2) / pow(fNpeScaleShift, 2);
369 
370  // Add the two strips together
371  return pesCorr1 + pesCorr2;
372 }
373 
374 double CRTHitRecoAlg::CorrectTime(CRTStrip strip1, CRTStrip strip2, TVector3 position){
375  geo::Point_t pos {position.X(), position.Y(), position.Z()};
376 
377  // Get the strip name from the channel ID
378  std::string name1 = fCrtGeo.ChannelToStripName(strip1.channel);
379  std::string name2 = fCrtGeo.ChannelToStripName(strip2.channel);
380 
381  // Get the distance from the CRT hit to the sipm end
382  double stripDist1 = fCrtGeo.DistanceDownStrip(pos, name1);
383  double stripDist2 = fCrtGeo.DistanceDownStrip(pos, name2);
384 
385  // Correct the measured time for propagation delay
386  double timeCorr1 = strip1.t0 - stripDist1 * fPropDelay * 1e-3;
387  double timeCorr2 = strip2.t0 - stripDist2 * fPropDelay * 1e-3;
388 
389  // Find the corrected pe
390  double pesCorr1 = strip1.pes * pow(stripDist1 - fNpeScaleShift, 2) / pow(fNpeScaleShift, 2);
391  double pesCorr2 = strip2.pes * pow(stripDist2 - fNpeScaleShift, 2) / pow(fNpeScaleShift, 2);
392 
393  // Use to correct for time walk
394  timeCorr1 -= (fTDelayNorm * exp(-0.5 * pow((pesCorr1 - fTDelayShift) / fTDelaySigma, 2)) + fTDelayOffset) * 1e-3;
395  timeCorr2 -= (fTDelayNorm * exp(-0.5 * pow((pesCorr2 - fTDelayShift) / fTDelaySigma, 2)) + fTDelayOffset) * 1e-3;
396 
397  // Average the two strips times
398  return (timeCorr1 + timeCorr2) / 2.;
399 }
400 
401 }
float z_err
position uncertainty in z-direction (cm).
Definition: CRTHit.hh:43
process_name opflash particleana ie ie ie z
float x_err
position uncertainty in x-direction (cm).
Definition: CRTHit.hh:39
std::map< uint8_t, std::vector< std::pair< int, float > > > pesmap
Saves signal hit information (FEB, local-channel and PE) .
Definition: CRTHit.hh:26
std::vector< uint8_t > feb_id
FEB address.
Definition: CRTHit.hh:25
double ts1_ns
Timestamp T1 ([signal time w.r.t. Trigger time]), in UTC absolute time scale in nanoseconds from the ...
Definition: CRTHit.hh:34
process_name opflash particleana ie x
int plane
Name of the CRT wall (in the form of numbers).
Definition: CRTHit.hh:36
float peshit
Total photo-electron (PE) in a crt hit.
Definition: CRTHit.hh:27
float y_err
position uncertainty in y-direction (cm).
Definition: CRTHit.hh:41
double TPCTick2Time(double const tick) const
Given TPC time-tick (waveform index), returns electronics clock [us].
CRTStrip CreateCRTStrip(art::Ptr< sbnd::crt::CRTData > sipm1, art::Ptr< sbnd::crt::CRTData > sipm2, size_t ind)
double ts0_ns_corr
[Honestly, not sure at this point, it was there since long time (BB)]
Definition: CRTHit.hh:33
double ts0_s_corr
[Honestly, not sure at this point, it was there since long time (BB)]
Definition: CRTHit.hh:30
CRTModuleGeo GetModule(std::string moduleName) const
uint64_t ts0_s
Second-only part of timestamp T0.
Definition: CRTHit.hh:29
std::pair< std::string, unsigned > tagger
std::pair< double, double > DistanceBetweenSipms(art::Ptr< sbnd::crt::CRTData > sipm1, art::Ptr< sbnd::crt::CRTData > sipm2)
process_name gaushit a
float z_pos
position in z-direction (cm).
Definition: CRTHit.hh:42
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
double ts0_ns
Timestamp T0 (from White Rabbit), in UTC absolute time scale in nanoseconds from the Epoch...
Definition: CRTHit.hh:32
T abs(T value)
process_name opflash particleana ie ie y
std::string ChannelToStripName(size_t channel) const
enum::sbnd::CRTPlane GetPlaneIndex(std::string tagger)
std::map< std::pair< std::string, unsigned >, std::vector< CRTStrip > > CreateTaggerStrips(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, std::vector< art::Ptr< sbnd::crt::CRTData >> data)
double DistanceDownStrip(geo::Point_t position, std::string stripName) const
double CorrectNpe(CRTStrip strip1, CRTStrip strip2, TVector3 position)
CRTStripGeo GetStrip(std::string stripName) const
std::vector< std::pair< sbn::crt::CRTHit, std::vector< int > > > CreateCRTHits(std::map< std::pair< std::string, unsigned >, std::vector< CRTStrip >> taggerStrips)
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
std::pair< std::string, unsigned > ChannelToTagger(uint32_t channel)
std::vector< double > StripLimitsWithChargeSharing(std::string stripName, double x, double ex)
float y_pos
position in y-direction (cm).
Definition: CRTHit.hh:40
double mean(const std::vector< short > &wf, size_t start, size_t nsample)
Definition: UtilFunc.cxx:13
sbn::crt::CRTHit FillCrtHit(std::vector< uint8_t > tfeb_id, std::map< uint8_t, std::vector< std::pair< int, float >>> tpesmap, float peshit, double time, int plane, double x, double ex, double y, double ey, double z, double ez, std::string tagger)
Contains all timing reference information for the detector.
float x_pos
position in x-direction (cm).
Definition: CRTHit.hh:38
BEGIN_PROLOG sequence::SlidingWindowTriggerPatternsOppositeWindows END_PROLOG simSlidingORM6O6 effSlidingORW output
do i e
std::vector< double > CrtOverlap(std::vector< double > strip1, std::vector< double > strip2)
std::vector< double > ChannelToLimits(CRTStrip strip)
stream1 can override from command line with o or output services user sbnd
double CorrectTime(CRTStrip strip1, CRTStrip strip2, TVector3 position)
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
std::string tagger
Name of the CRT wall (in the form of strings).
Definition: CRTHit.hh:45
auto const detProp
CRTHitRecoAlg(const Config &config, double g4RefTime)