LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
BeamFlashTrackMatchTaggerAlg.cxx
Go to the documentation of this file.
1 
13 
14 #include "fhiclcpp/ParameterSet.h"
15 
22 
23 #include <limits>
24 #include <utility>
25 #include <vector>
26 
27 #include "TH1F.h"
28 #include "TTree.h"
29 #include "TVector3.h"
30 
32  : COSMIC_TYPE_FLASHMATCH(anab::CosmicTagID_t::kFlash_BeamIncompatible)
33  , COSMIC_TYPE_OUTSIDEDRIFT(anab::CosmicTagID_t::kOutsideDrift_Partial)
34  , DEBUG_FLAG(p.get<bool>("RunDebugMode", false))
35  , fMinTrackLength(p.get<float>("MinTrackLength"))
36  , fMinOpHitPE(p.get<float>("MinOpHitPE", 0.1))
37  , fMIPdQdx(p.get<float>("MIPdQdx", 2.1))
38  , fOpDetSaturation(p.get<float>("OpDetSaturation", 200.))
39  , fSingleChannelCut(p.get<float>("SingleChannelCut"))
40  , fCumulativeChannelThreshold(p.get<float>("CumulativeChannelThreshold"))
41  , fCumulativeChannelCut(p.get<unsigned int>("CumulativeChannelCut"))
42  , fIntegralCut(p.get<float>("IntegralCut"))
43  , fMakeOutsideDriftTags(p.get<bool>("MakeOutsideDriftTags", false))
44  , fNormalizeHypothesisToFlash(p.get<bool>("NormalizeHypothesisToFlash"))
45 {}
46 
48  TH1F* hist_flash,
49  TH1F* hist_hyp)
50 {
51  cTree = tree;
52 
53  cOpDetHist_flash = hist_flash;
54  cOpDetHist_flash->SetNameTitle("opdet_hist_flash", "Optical Detector Occupancy, Flash");
55 
56  cOpDetHist_hyp = hist_hyp;
57  cOpDetHist_hyp->SetNameTitle("opdet_hist_hyp", "Optical Detector Occupancy, Hypothesis");
58 
60  cTree->Branch("opdet_hyp", &cOpDetVector_hyp);
61  cTree->Branch("opdet_flash", &cOpDetVector_flash);
62  cTree->Branch("opdet_hist_flash", "TH1F", cOpDetHist_flash);
63  cTree->Branch("opdet_hist_hyp", "TH1F", cOpDetHist_hyp);
64 }
65 
67  std::vector<recob::OpFlash> const& flashVector,
68  std::vector<recob::Track> const& trackVector,
69  std::vector<anab::CosmicTag>& cosmicTagVector,
70  std::vector<size_t>& assnTrackTagVector,
71  Providers_t providers,
73  opdet::OpDigiProperties const& opdigip)
74 {
75 
76  auto const& geom = *(providers.get<geo::GeometryCore>());
77 
78  std::vector<const recob::OpFlash*> flashesOnBeamTime;
79  for (auto const& flash : flashVector) {
80  if (!flash.OnBeamTime()) continue;
81  flashesOnBeamTime.push_back(&flash);
82  }
83 
84  //make sure this association vector is initialized properly
85  assnTrackTagVector.resize(trackVector.size(), std::numeric_limits<size_t>::max());
86  cosmicTagVector.reserve(trackVector.size());
87 
88  for (size_t track_i = 0; track_i < trackVector.size(); track_i++) {
89 
90  recob::Track const& track(trackVector[track_i]);
91 
92  if (track.Length() < fMinTrackLength) continue;
93 
94  //get the begin and end points of this track
95  TVector3 const& pt_begin = track.LocationAtPoint<TVector3>(0);
96  TVector3 const& pt_end = track.LocationAtPoint<TVector3>(track.NumberTrajectoryPoints() - 1);
97  std::vector<float> xyz_begin = {(float)pt_begin.x(), (float)pt_begin.y(), (float)pt_begin.z()};
98  std::vector<float> xyz_end = {(float)pt_end.x(), (float)pt_end.y(), (float)pt_end.z()};
99 
100  //check if this track is outside the drift window, and if it is continue
101  if (!InDriftWindow(pt_begin.x(), pt_end.x(), geom)) {
102  if (fMakeOutsideDriftTags) {
103  cosmicTagVector.emplace_back(xyz_begin, xyz_end, 1., COSMIC_TYPE_OUTSIDEDRIFT);
104  assnTrackTagVector[track_i] = cosmicTagVector.size() - 1;
105  }
106  continue;
107  }
108 
109  //get light hypothesis for track
110  std::vector<float> lightHypothesis = GetMIPHypotheses(track, providers, pvs, opdigip);
111 
112  //check compatibility with beam flash
113  bool compatible = false;
114  for (const recob::OpFlash* flashPointer : flashesOnBeamTime) {
115  CompatibilityResultType result = CheckCompatibility(lightHypothesis, flashPointer, geom);
116  if (result == CompatibilityResultType::kCompatible) compatible = true;
117  if (DEBUG_FLAG) {
118  PrintTrackProperties(track);
119  PrintFlashProperties(*flashPointer);
120  PrintHypothesisFlashComparison(lightHypothesis, flashPointer, geom, result);
121  }
122  }
123 
124  //make tag
125  float cosmicScore = 1.;
126  if (compatible) cosmicScore = 0.;
127  cosmicTagVector.emplace_back(xyz_begin, xyz_end, cosmicScore, COSMIC_TYPE_FLASHMATCH);
128  assnTrackTagVector[track_i] = cosmicTagVector.size() - 1;
129  }
130 }
131 
132 //this compares the hypothesis to the flash itself.
134  unsigned int const run,
135  unsigned int const event,
136  std::vector<recob::OpFlash> const& flashVector,
137  std::vector<recob::Track> const& trackVector,
138  Providers_t providers,
140  opdet::OpDigiProperties const& opdigip)
141 {
142 
143  auto const& geom = *(providers.get<geo::GeometryCore>());
144 
145  cFlashComparison_p.run = run;
146  cFlashComparison_p.event = event;
147 
148  std::vector<std::pair<unsigned int, const recob::OpFlash*>> flashesOnBeamTime;
149  for (unsigned int i = 0; i < flashVector.size(); i++) {
150  recob::OpFlash const& flash = flashVector[i];
151  if (!flash.OnBeamTime()) continue;
152  flashesOnBeamTime.push_back(std::make_pair(i, &flash));
153  }
154 
155  for (size_t track_i = 0; track_i < trackVector.size(); track_i++) {
156 
157  recob::Track const& track(trackVector[track_i]);
158 
159  if (track.Length() < fMinTrackLength) continue;
160 
161  //get the begin and end points of this track
162  TVector3 const& pt_begin = track.LocationAtPoint<TVector3>(0);
163  TVector3 const& pt_end = track.LocationAtPoint<TVector3>(track.NumberTrajectoryPoints() - 1);
164  std::vector<float> xyz_begin = {(float)pt_begin.x(), (float)pt_begin.y(), (float)pt_begin.z()};
165  std::vector<float> xyz_end = {(float)pt_end.x(), (float)pt_end.y(), (float)pt_end.z()};
166 
167  //check if this track is outside the drift window, and if it is continue
168  if (!InDriftWindow(pt_begin.x(), pt_end.x(), geom)) continue;
169 
170  cFlashComparison_p.trk_startx = pt_begin.x();
171  cFlashComparison_p.trk_starty = pt_begin.y();
172  cFlashComparison_p.trk_startz = pt_begin.z();
173  cFlashComparison_p.trk_endx = pt_end.x();
174  cFlashComparison_p.trk_endy = pt_end.y();
175  cFlashComparison_p.trk_endz = pt_end.z();
176 
177  //get light hypothesis for track
178  cOpDetVector_hyp = GetMIPHypotheses(track, providers, pvs, opdigip);
179 
180  cFlashComparison_p.hyp_index = track_i;
187  geom);
188 
189  for (auto flash : flashesOnBeamTime) {
190  cOpDetVector_flash = std::vector<float>(geom.NOpDets(), 0);
192  for (size_t c = 0; c <= geom.MaxOpChannel(); c++) {
193  if (geom.IsValidOpChannel(c)) {
194  unsigned int OpDet = geom.OpDetFromOpChannel(c);
195  cOpDetVector_flash[OpDet] += flash.second->PE(c);
196  }
197  }
198  for (size_t o = 0; o < cOpDetVector_flash.size(); o++)
200 
201  cFlashComparison_p.flash_index = flash.first;
202  cFlashComparison_p.flash_totalPE = flash.second->TotalPE();
203  cFlashComparison_p.flash_y = flash.second->YCenter();
204  cFlashComparison_p.flash_sigmay = flash.second->YWidth();
205  cFlashComparison_p.flash_z = flash.second->ZCenter();
206  cFlashComparison_p.flash_sigmaz = flash.second->ZWidth();
207 
209 
210  cTree->Fill();
211  } //end loop over flashes
212 
213  } //end loop over tracks
214 }
215 
216 //this compares the hypothesis to the flash itself.
218  unsigned int const run,
219  unsigned int const event,
220  std::vector<recob::OpFlash> const& flashVector,
221  std::vector<simb::MCParticle> const& mcParticleVector,
222  Providers_t providers,
224  opdet::OpDigiProperties const& opdigip)
225 {
226 
227  auto const& geom = *(providers.get<geo::GeometryCore>());
228 
229  cFlashComparison_p.run = run;
230  cFlashComparison_p.event = event;
231 
232  std::vector<std::pair<unsigned int, const recob::OpFlash*>> flashesOnBeamTime;
233  for (unsigned int i = 0; i < flashVector.size(); i++) {
234  recob::OpFlash const& flash = flashVector[i];
235  if (!flash.OnBeamTime()) continue;
236  flashesOnBeamTime.push_back(std::make_pair(i, &flash));
237  }
238 
239  for (size_t particle_i = 0; particle_i < mcParticleVector.size(); particle_i++) {
240 
241  simb::MCParticle const& particle(mcParticleVector[particle_i]);
242  if (particle.Process().compare("primary") != 0) continue;
243  if (particle.Trajectory().TotalLength() < fMinTrackLength) continue;
244 
245  //get the begin and end points of this track
246  size_t start_i = 0, end_i = particle.NumberTrajectoryPoints() - 1;
247  bool prev_inside = false;
248  for (size_t pt_i = 0; pt_i < particle.NumberTrajectoryPoints(); pt_i++) {
249  bool inside = InDetector(particle.Position(pt_i).Vect(), geom);
250  if (inside && !prev_inside) start_i = pt_i;
251  if (!inside && prev_inside) {
252  end_i = pt_i - 1;
253  break;
254  }
255  prev_inside = inside;
256  }
257  TVector3 const& pt_begin = particle.Position(start_i).Vect();
258  TVector3 const& pt_end = particle.Position(end_i).Vect();
259  std::vector<float> xyz_begin = {(float)pt_begin.x(), (float)pt_begin.y(), (float)pt_begin.z()};
260  std::vector<float> xyz_end = {(float)pt_end.x(), (float)pt_end.y(), (float)pt_end.z()};
261 
262  //check if this track is outside the drift window, and if it is continue
263  if (!InDriftWindow(pt_begin.x(), pt_end.x(), geom)) continue;
264 
265  cFlashComparison_p.trk_startx = pt_begin.x();
266  cFlashComparison_p.trk_starty = pt_begin.y();
267  cFlashComparison_p.trk_startz = pt_begin.z();
268  cFlashComparison_p.trk_endx = pt_end.x();
269  cFlashComparison_p.trk_endy = pt_end.y();
270  cFlashComparison_p.trk_endz = pt_end.z();
271 
272  //get light hypothesis for track
273  cOpDetVector_hyp = GetMIPHypotheses(particle, start_i, end_i, providers, pvs, opdigip);
274 
275  cFlashComparison_p.hyp_index = particle_i;
282  geom);
283 
284  for (auto flash : flashesOnBeamTime) {
285  cOpDetVector_flash = std::vector<float>(geom.NOpDets(), 0);
287  //for(size_t c=0; c<geom.NOpChannels(); c++){
288  for (size_t c = 0; c <= geom.MaxOpChannel(); c++) {
289  if (geom.IsValidOpChannel(c)) {
290  unsigned int OpDet = geom.OpDetFromOpChannel(c);
291  cOpDetVector_flash[OpDet] += flash.second->PE(c);
292  }
293  }
294  for (size_t o = 0; o < cOpDetVector_flash.size(); o++)
296  cFlashComparison_p.flash_index = flash.first;
297  cFlashComparison_p.flash_totalPE = flash.second->TotalPE();
298  cFlashComparison_p.flash_y = flash.second->YCenter();
299  cFlashComparison_p.flash_sigmay = flash.second->YWidth();
300  cFlashComparison_p.flash_z = flash.second->ZCenter();
301  cFlashComparison_p.flash_sigmaz = flash.second->ZWidth();
302 
304 
305  //cOpDetHist_flash->SetBins(cOpDetVector_flash.size(),0,cOpDetVector_flash.size());
306  for (size_t i = 0; i < cOpDetVector_flash.size(); i++)
307  cOpDetHist_flash->SetBinContent(i + 1, cOpDetVector_flash[i]);
308 
309  //cOpDetHist_hyp->SetBins(cOpDetVector_hyp.size(),0,cOpDetVector_hyp.size());
310  for (size_t i = 0; i < cOpDetVector_hyp.size(); i++)
311  cOpDetHist_hyp->SetBinContent(i + 1, cOpDetVector_hyp[i]);
312 
313  for (size_t i = 0; i < cOpDetVector_flash.size(); i++) {
314  std::cout << "Flash/Hyp " << i << " : " << cOpDetHist_flash->GetBinContent(i + 1) << " "
315  << cOpDetHist_hyp->GetBinContent(i + 1) << std::endl;
316  }
317 
318  cTree->Fill();
319  } //end loop over flashes
320 
321  } //end loop over tracks
322 }
323 
325  std::vector<float> const& opdetVector,
326  float& sum,
327  float& y,
328  float& sigmay,
329  float& z,
330  float& sigmaz,
331  geo::GeometryCore const& geom)
332 {
333  y = 0;
334  sigmay = 0;
335  z = 0;
336  sigmaz = 0;
337  sum = 0;
338  for (unsigned int opdet = 0; opdet < opdetVector.size(); opdet++) {
339  sum += opdetVector[opdet];
340  auto const xyz = geom.Cryostat().OpDet(opdet).GetCenter();
341  y += opdetVector[opdet] * xyz.Y();
342  z += opdetVector[opdet] * xyz.Z();
343  }
344 
345  y /= sum;
346  z /= sum;
347 
348  for (unsigned int opdet = 0; opdet < opdetVector.size(); opdet++) {
349  auto const xyz = geom.Cryostat().OpDet(opdet).GetCenter();
350  sigmay += (opdetVector[opdet] * xyz.Y() - y) * (opdetVector[opdet] * xyz.Y() - y);
351  sigmaz += (opdetVector[opdet] * xyz.Z() - y) * (opdetVector[opdet] * xyz.Z() - y);
352  }
353 
354  sigmay = std::sqrt(sigmay) / sum;
355  sigmaz = std::sqrt(sigmaz) / sum;
356 }
357 
359  geo::GeometryCore const& geom)
360 {
361  if (pt.x() < 0 || pt.x() > 2 * geom.DetHalfWidth()) return false;
362  if (std::abs(pt.y()) > geom.DetHalfHeight()) return false;
363  if (pt.z() < 0 || pt.z() > geom.DetLength()) return false;
364  return true;
365 }
366 
368  double end_x,
369  geo::GeometryCore const& geom)
370 {
371  if (start_x < 0. || end_x < 0.) return false;
372  if (start_x > 2 * geom.DetHalfWidth() || end_x > 2 * geom.DetHalfWidth()) return false;
373  return true;
374 }
375 
377  TVector3 const& pt1,
378  TVector3 const& pt2,
379  std::vector<float>& lightHypothesis,
380  float& totalHypothesisPE,
381  geo::GeometryCore const& geom,
383  float const& PromptMIPScintYield,
384  float XOffset)
385 {
386 
387  double xyz_segment[3];
388  xyz_segment[0] = 0.5 * (pt2.x() + pt1.x()) + XOffset;
389  xyz_segment[1] = 0.5 * (pt2.y() + pt1.y());
390  xyz_segment[2] = 0.5 * (pt2.z() + pt1.z());
391 
392  //get the visibility vector
393  auto const& PointVisibility = pvs.GetAllVisibilities(xyz_segment);
394 
395  //check pointer, as it may be null if given a y/z outside some range
396  if (!PointVisibility) return;
397 
398  //get the amount of light
399  float LightAmount = PromptMIPScintYield * (pt2 - pt1).Mag();
400 
401  for (size_t opdet_i = 0; opdet_i < pvs.NOpChannels(); opdet_i++) {
402  lightHypothesis[opdet_i] += PointVisibility[opdet_i] * LightAmount;
403  totalHypothesisPE += PointVisibility[opdet_i] * LightAmount;
404 
405  //apply saturation limit
406  if (lightHypothesis[opdet_i] > fOpDetSaturation) {
407  totalHypothesisPE -= (lightHypothesis[opdet_i] - fOpDetSaturation);
408  lightHypothesis[opdet_i] = fOpDetSaturation;
409  }
410  }
411 
412 } //end AddLightFromSegment
413 
415  std::vector<float>& lightHypothesis,
416  float const& totalHypothesisPE,
417  geo::GeometryCore const& geom)
418 {
419  for (size_t opdet_i = 0; opdet_i < geom.NOpDets(); opdet_i++)
420  lightHypothesis[opdet_i] /= totalHypothesisPE;
421 }
422 
423 // Get a hypothesis for the light collected for a track
425  recob::Track const& track,
426  Providers_t providers,
428  opdet::OpDigiProperties const& opdigip,
429  float XOffset)
430 {
431  auto const& geom = *(providers.get<geo::GeometryCore>());
432  auto const& larp = *(providers.get<detinfo::LArProperties>());
433  std::vector<float> lightHypothesis(geom.NOpDets(), 0);
434  float totalHypothesisPE = 0;
435  const float PromptMIPScintYield =
436  larp.ScintYield() * larp.ScintYieldRatio() * opdigip.QE() * fMIPdQdx;
437 
438  //get QE from ubChannelConfig, which gives per tube, so goes in AddLightFromSegment
439  //VisibleEnergySeparation(step);
440 
441  for (size_t pt = 1; pt < track.NumberTrajectoryPoints(); pt++)
442  AddLightFromSegment(track.LocationAtPoint<TVector3>(pt - 1),
443  track.LocationAtPoint<TVector3>(pt),
444  lightHypothesis,
445  totalHypothesisPE,
446  geom,
447  pvs,
448  PromptMIPScintYield,
449  XOffset);
450 
451  if (fNormalizeHypothesisToFlash && totalHypothesisPE > std::numeric_limits<float>::epsilon())
452  NormalizeLightHypothesis(lightHypothesis, totalHypothesisPE, geom);
453 
454  return lightHypothesis;
455 
456 } //end GetMIPHypotheses
457 
458 // Get a hypothesis for the light collected for a particle trajectory
460  simb::MCParticle const& particle,
461  size_t start_i,
462  size_t end_i,
463  Providers_t providers,
465  opdet::OpDigiProperties const& opdigip,
466  float XOffset)
467 {
468  auto const& geom = *(providers.get<geo::GeometryCore>());
469  auto const& larp = *(providers.get<detinfo::LArProperties>());
470  std::vector<float> lightHypothesis(geom.NOpDets(), 0);
471  float totalHypothesisPE = 0;
472  const float PromptMIPScintYield =
473  larp.ScintYield() * larp.ScintYieldRatio() * opdigip.QE() * fMIPdQdx;
474 
475  for (size_t pt = start_i + 1; pt <= end_i; pt++)
476  AddLightFromSegment(particle.Position(pt - 1).Vect(),
477  particle.Position(pt).Vect(),
478  lightHypothesis,
479  totalHypothesisPE,
480  geom,
481  pvs,
482  PromptMIPScintYield,
483  XOffset);
484 
485  if (fNormalizeHypothesisToFlash && totalHypothesisPE > std::numeric_limits<float>::epsilon())
486  NormalizeLightHypothesis(lightHypothesis, totalHypothesisPE, geom);
487 
488  return lightHypothesis;
489 
490 } //end GetMIPHypotheses
491 
492 //---------------------------------------
493 // Check whether a hypothesis can be accomodated in a flash
494 // Flashes fail if 1 bin is far in excess of the observed signal
495 // or if the whole flash intensity is much too large for the hypothesis.
496 // MIP dEdx is assumed for now. Accounting for real dQdx will
497 // improve performance of this algorithm.
498 //---------------------------------------
500 cosmic::BeamFlashTrackMatchTaggerAlg::CheckCompatibility(std::vector<float> const& lightHypothesis,
501  const recob::OpFlash* flashPointer,
502  geo::GeometryCore const& geom)
503 {
504  float hypothesis_integral = 0;
505  float flash_integral = 0;
506  unsigned int cumulativeChannels = 0;
507 
508  std::vector<double> PEbyOpDet(geom.NOpDets(), 0);
509  //for (unsigned int c = 0; c < geom.NOpChannels(); c++){
510  for (unsigned int c = 0; c <= geom.MaxOpChannel(); c++) {
511  if (geom.IsValidOpChannel(c)) {
512  unsigned int o = geom.OpDetFromOpChannel(c);
513  PEbyOpDet[o] += flashPointer->PE(c);
514  }
515  }
516 
517  float hypothesis_scale = 1.;
518  if (fNormalizeHypothesisToFlash) hypothesis_scale = flashPointer->TotalPE();
519 
520  for (size_t pmt_i = 0; pmt_i < lightHypothesis.size(); pmt_i++) {
521 
522  flash_integral += PEbyOpDet[pmt_i];
523 
524  if (lightHypothesis[pmt_i] < std::numeric_limits<float>::epsilon()) continue;
525  hypothesis_integral += lightHypothesis[pmt_i] * hypothesis_scale;
526 
527  if (PEbyOpDet[pmt_i] < fMinOpHitPE) continue;
528 
529  float diff_scaled = (lightHypothesis[pmt_i] * hypothesis_scale - PEbyOpDet[pmt_i]) /
530  std::sqrt(lightHypothesis[pmt_i] * hypothesis_scale);
531 
532  if (diff_scaled > fSingleChannelCut) return CompatibilityResultType::kSingleChannelCut;
533 
534  if (diff_scaled > fCumulativeChannelThreshold) cumulativeChannels++;
535  if (cumulativeChannels >= fCumulativeChannelCut)
536  return CompatibilityResultType::kCumulativeChannelCut;
537  }
538 
539  if ((hypothesis_integral - flash_integral) / std::sqrt(hypothesis_integral) > fIntegralCut)
540  return CompatibilityResultType::kIntegralCut;
541 
542  return CompatibilityResultType::kCompatible;
543 }
544 
545 float cosmic::BeamFlashTrackMatchTaggerAlg::CalculateChi2(std::vector<float> const& light_flash,
546  std::vector<float> const& light_track)
547 {
548 
549  float chi2 = 0;
550  for (size_t pmt_i = 0; pmt_i < light_flash.size(); pmt_i++) {
551 
552  if (light_flash[pmt_i] < fMinOpHitPE) continue;
553 
554  float err2 = 1;
555  if (light_track[pmt_i] > 1) err2 = light_track[pmt_i];
556 
557  chi2 +=
558  (light_flash[pmt_i] - light_track[pmt_i]) * (light_flash[pmt_i] - light_track[pmt_i]) / err2;
559  }
560 
561  return chi2;
562 }
563 
565  std::ostream* output)
566 {
567  *output << "----------------------------------------------" << std::endl;
568  *output << "Track properties: ";
569  *output << "\n\tLength=" << track.Length();
570 
571  auto const& pt_begin = track.LocationAtPoint(0);
572  *output << "\n\tBegin Location (x,y,z)=(" << pt_begin.x() << "," << pt_begin.y() << ","
573  << pt_begin.z() << ")";
574 
575  auto const& pt_end = track.LocationAtPoint(track.NumberTrajectoryPoints() - 1);
576  *output << "\n\tEnd Location (x,y,z)=(" << pt_end.x() << "," << pt_end.y() << "," << pt_end.z()
577  << ")";
578 
579  *output << "\n\tTrajectoryPoints=" << track.NumberTrajectoryPoints();
580  *output << std::endl;
581  *output << "----------------------------------------------" << std::endl;
582 }
583 
585  std::ostream* output)
586 {
587  *output << "----------------------------------------------" << std::endl;
588  *output << "Flash properties: ";
589 
590  *output << "\n\tTime=" << flash.Time();
591  *output << "\n\tOnBeamTime=" << flash.OnBeamTime();
592  *output << "\n\ty position (center,width)=(" << flash.YCenter() << "," << flash.YWidth() << ")";
593  *output << "\n\tz position (center,width)=(" << flash.ZCenter() << "," << flash.ZWidth() << ")";
594  *output << "\n\tTotal PE=" << flash.TotalPE();
595 
596  *output << std::endl;
597  *output << "----------------------------------------------" << std::endl;
598 }
599 
601  std::vector<float> const& lightHypothesis,
602  const recob::OpFlash* flashPointer,
603  geo::GeometryCore const& geom,
605  std::ostream* output)
606 {
607 
608  *output << "----------------------------------------------" << std::endl;
609  *output << "Hypothesis-flash comparison: ";
610 
611  float hypothesis_integral = 0;
612  float flash_integral = 0;
613 
614  float hypothesis_scale = 1.;
615  if (fNormalizeHypothesisToFlash) hypothesis_scale = flashPointer->TotalPE();
616 
617  std::vector<double> PEbyOpDet(geom.NOpDets(), 0);
618  //for (unsigned int c = 0; c < geom.NOpChannels(); c++){
619  for (unsigned int c = 0; c <= geom.MaxOpChannel(); c++) {
620  if (geom.IsValidOpChannel(c)) {
621  unsigned int o = geom.OpDetFromOpChannel(c);
622  PEbyOpDet[o] += flashPointer->PE(c);
623  }
624  }
625 
626  for (size_t pmt_i = 0; pmt_i < lightHypothesis.size(); pmt_i++) {
627 
628  flash_integral += PEbyOpDet[pmt_i];
629 
630  *output << "\n\t pmt_i=" << pmt_i << ", (hypothesis,flash)=("
631  << lightHypothesis[pmt_i] * hypothesis_scale << "," << PEbyOpDet[pmt_i] << ")";
632 
633  if (lightHypothesis[pmt_i] < std::numeric_limits<float>::epsilon()) continue;
634 
635  *output << " difference="
636  << (lightHypothesis[pmt_i] * hypothesis_scale - PEbyOpDet[pmt_i]) /
637  std::sqrt(lightHypothesis[pmt_i] * hypothesis_scale);
638 
639  hypothesis_integral += lightHypothesis[pmt_i] * hypothesis_scale;
640  }
641 
642  *output << "\n\t TOTAL (hypothesis,flash)=(" << hypothesis_integral << "," << flash_integral
643  << ")"
644  << " difference="
645  << (hypothesis_integral - flash_integral) / std::sqrt(hypothesis_integral);
646 
647  *output << std::endl;
648  *output << "End result=" << result << std::endl;
649  *output << "----------------------------------------------" << std::endl;
650 }
unsigned int NumberTrajectoryPoints() const
Definition: MCParticle.h:219
const TLorentzVector & Position(const int i=0) const
Definition: MCParticle.h:220
CompatibilityResultType CheckCompatibility(std::vector< float > const &lightHypothesis, const recob::OpFlash *flashPointer, geo::GeometryCore const &geom)
BeamFlashTrackMatchTaggerAlg(fhicl::ParameterSet const &p)
const simb::MCTrajectory & Trajectory() const
Definition: MCParticle.h:254
enum anab::cosmic_tag_id CosmicTagID_t
Float_t y
Definition: compare.C:6
Point_t const & LocationAtPoint(size_t i) const
Access to track position at different points.
Definition: Track.h:160
Length_t DetHalfWidth(TPCID const &tpcid=tpc_zero) const
Returns the half width of the active volume of the specified TPC.
Double_t z
Definition: plot.C:276
void RunHypothesisComparison(unsigned int const, unsigned int const, std::vector< recob::OpFlash > const &, std::vector< recob::Track > const &, Providers_t, phot::PhotonVisibilityService const &, opdet::OpDigiProperties const &)
float CalculateChi2(std::vector< float > const &, std::vector< float > const &)
size_t NumberTrajectoryPoints() const
Various functions related to the presence and the number of (valid) points.
Definition: Track.h:136
constexpr auto abs(T v)
Returns the absolute value of the argument.
Provider const * get() const
Returns the provider with the specified type.
Definition: ProviderPack.h:182
double PE(unsigned int i) const
Definition: OpFlash.h:134
std::string Process() const
Definition: MCParticle.h:216
CryostatGeo const & Cryostat(CryostatID const &cryoid=cryostat_zero) const
Returns the specified cryostat.
void RunCompatibilityCheck(std::vector< recob::OpFlash > const &, std::vector< recob::Track > const &, std::vector< anab::CosmicTag > &, std::vector< size_t > &, Providers_t, phot::PhotonVisibilityService const &, opdet::OpDigiProperties const &)
Length_t DetLength(TPCID const &tpcid=tpc_zero) const
Returns the length of the active volume of the specified TPC.
unsigned int OpDetFromOpChannel(int opChannel) const
Convert unique channel to detector number.
double ZCenter() const
Definition: OpFlash.h:162
Access the description of detector geometry.
std::vector< float > GetMIPHypotheses(recob::Track const &track, Providers_t providers, phot::PhotonVisibilityService const &pvs, opdet::OpDigiProperties const &, float XOffset=0)
double Time() const
Definition: OpFlash.h:118
double QE() const noexcept
Returns quantum efficiency.
double Length(size_t p=0) const
Access to various track properties.
Definition: Track.h:207
TText * pt2
Definition: plot.C:64
void NormalizeLightHypothesis(std::vector< float > &lightHypothesis, float const &totalHypothesisPE, geo::GeometryCore const &geom)
const OpDetGeo & OpDet(unsigned int iopdet) const
Return the iopdet&#39;th optical detector in the cryostat.
Definition: CryostatGeo.cxx:95
int OnBeamTime() const
Definition: OpFlash.h:186
void AddLightFromSegment(TVector3 const &pt1, TVector3 const &pt2, std::vector< float > &lightHypothesis, float &totalHypothesisPE, geo::GeometryCore const &geom, phot::PhotonVisibilityService const &pvs, float const &PromptMIPScintYield, float XOffset)
void PrintTrackProperties(recob::Track const &, std::ostream *output=&std::cout)
TMarker * pt
Definition: egs.C:25
unsigned int MaxOpChannel() const
Largest optical channel number.
Description of geometry of one entire detector.
Definition: GeometryCore.h:119
MappedCounts_t GetAllVisibilities(Point const &p, bool wantReflected=false) const
void SetHypothesisComparisonTree(TTree *, TH1F *, TH1F *)
unsigned int NOpDets() const
Number of OpDets in the whole detector.
Encapsulate the geometry of an optical detector.
geo::Point_t const & GetCenter() const
Definition: OpDetGeo.h:72
double YWidth() const
Definition: OpFlash.h:158
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
Definition: StdUtils.h:120
double TotalLength() const
void PrintHypothesisFlashComparison(std::vector< float > const &, const recob::OpFlash *, geo::GeometryCore const &geom, CompatibilityResultType, std::ostream *output=&std::cout)
Container for a list of pointers to providers.
Definition: ProviderPack.h:111
bool InDriftWindow(double, double, geo::GeometryCore const &)
void FillFlashProperties(std::vector< float > const &opdetVector, float &, float &, float &, float &, float &, geo::GeometryCore const &geom)
Length_t DetHalfHeight(TPCID const &tpcid=tpc_zero) const
Returns the half height of the active volume of the specified TPC.
double TotalPE() const
Definition: OpFlash.cxx:94
TText * pt1
Definition: plot.C:61
bool InDetector(TVector3 const &, geo::GeometryCore const &)
Double_t sum
Definition: plot.C:31
double YCenter() const
Definition: OpFlash.h:154
Float_t track
Definition: plot.C:35
bool IsValidOpChannel(int opChannel) const
Is this a valid OpChannel number?
art framework interface to geometry description
Track from a non-cascading particle.A recob::Track consists of a recob::TrackTrajectory, plus additional members relevant for a "fitted" track:
Definition: Track.h:49
double ZWidth() const
Definition: OpFlash.h:166
Event finding and building.
void PrintFlashProperties(recob::OpFlash const &, std::ostream *output=&std::cout)