All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OpFlashAlg.cxx
Go to the documentation of this file.
1 // -*- mode: c++; c-basic-offset: 2; -*-
2 /*!
3  * Title: OpFlash Algorithims
4  * Authors, editors: Ben Jones, MIT
5  * Wes Ketchum wketchum@lanl.gov
6  * Gleb Sinev gleb.sinev@duke.edu
7  * Alex Himmel ahimmel@fnal.gov
8  *
9  * Description:
10  * These are the algorithms used by OpFlashFinder to produce flashes.
11  */
12 
13 #include "OpFlashAlg.h"
14 
15 #include "TFile.h"
16 #include "TH1.h"
17 
25 
26 #include <algorithm>
27 #include <cmath>
28 #include <iostream>
29 #include <numeric> // std::iota()
30 
31 namespace opdet {
32 
33  //----------------------------------------------------------------------------
34  void
35  writeHistogram(std::vector<double> const& binned)
36  {
37  TH1D* binned_histogram = new TH1D("binned_histogram",
38  "Collection of All OpHits;Time (ms);PEs",
39  binned.size(),
40  0,
41  binned.size());
42  for (size_t i = 0; i < binned.size(); ++i)
43  binned_histogram->SetBinContent(i, binned.at(i));
44 
45  TFile f_out("output_hist.root", "RECREATE");
46  binned_histogram->Write();
47  f_out.Close();
48 
49  delete binned_histogram;
50  }
51 
52  //----------------------------------------------------------------------------
53  void
54  checkOnBeamFlash(std::vector<recob::OpFlash> const& FlashVector)
55  {
56  for (auto const& flash : FlashVector)
57  if (flash.OnBeamTime() == 1)
58  std::cout << "OnBeamFlash with time " << flash.Time() << std::endl;
59  }
60 
61  //----------------------------------------------------------------------------
62  void
63  RunFlashFinder(std::vector<recob::OpHit> const& HitVector,
64  std::vector<recob::OpFlash>& FlashVector,
65  std::vector<std::vector<int>>& AssocList,
66  double const BinWidth,
67  geo::GeometryCore const& geom,
68  float const FlashThreshold,
69  float const WidthTolerance,
70  detinfo::DetectorClocksData const& ClocksData,
71  float const TrigCoinc)
72  {
73  // Initial size for accumulators - will be automatically extended if needed
74  int initialsize = 6400;
75 
76  // These are the accumulators which will hold broad-binned light yields
77  std::vector<double> Binned1(initialsize);
78  std::vector<double> Binned2(initialsize);
79 
80  // These will keep track of which pulses put activity in each bin
81  std::vector<std::vector<int>> Contributors1(initialsize);
82  std::vector<std::vector<int>> Contributors2(initialsize);
83 
84  // These will keep track of where we have met the flash condition
85  // (in order to prevent second pointless loop)
86  std::vector<int> FlashesInAccumulator1;
87  std::vector<int> FlashesInAccumulator2;
88 
89  double minTime = std::numeric_limits<float>::max();
90  for (auto const& hit : HitVector)
91  if (hit.PeakTime() < minTime) minTime = hit.PeakTime();
92 
93  for (auto const& hit : HitVector) {
94 
95  double peakTime = hit.PeakTime();
96 
97  unsigned int AccumIndex1 = GetAccumIndex(peakTime, minTime, BinWidth, 0.0);
98 
99  unsigned int AccumIndex2 = GetAccumIndex(peakTime, minTime, BinWidth, BinWidth / 2.0);
100 
101  // Extend accumulators if needed (2 always larger than 1)
102  if (AccumIndex2 >= Binned1.size()) {
103  std::cout << "Extending vectors to " << AccumIndex2 * 1.2 << std::endl;
104  Binned1.resize(AccumIndex2 * 1.2);
105  Binned2.resize(AccumIndex2 * 1.2);
106  Contributors1.resize(AccumIndex2 * 1.2);
107  Contributors2.resize(AccumIndex2 * 1.2);
108  }
109 
110  size_t const hitIndex = &hit - &HitVector[0];
111 
112  FillAccumulator(AccumIndex1,
113  hitIndex,
114  hit.PE(),
116  Binned1,
117  Contributors1,
118  FlashesInAccumulator1);
119 
120  FillAccumulator(AccumIndex2,
121  hitIndex,
122  hit.PE(),
124  Binned2,
125  Contributors2,
126  FlashesInAccumulator2);
127 
128  } // End loop over hits
129 
130  // Now start to create flashes.
131  // First, need vector to keep track of which hits belong to which flashes
132  std::vector<std::vector<int>> HitsPerFlash;
133 
134  //if (Frame == 1) writeHistogram(Binned1);
135 
136  AssignHitsToFlash(FlashesInAccumulator1,
137  FlashesInAccumulator2,
138  Binned1,
139  Binned2,
140  Contributors1,
141  Contributors2,
142  HitVector,
143  HitsPerFlash,
144  FlashThreshold);
145 
146  // Now we do the fine grained part.
147  // Subdivide each flash into sub-flashes with overlaps within hit widths
148  // (assumed wider than photon travel time)
149  std::vector<std::vector<int>> RefinedHitsPerFlash;
150  for (auto const& HitsThisFlash : HitsPerFlash)
152  HitsThisFlash, HitVector, RefinedHitsPerFlash, WidthTolerance, FlashThreshold);
153 
154  // Now we have all our hits assigned to a flash.
155  // Make the recob::OpFlash objects
156  for (auto const& HitsPerFlashVec : RefinedHitsPerFlash)
157  ConstructFlash(HitsPerFlashVec, HitVector, FlashVector, geom, ClocksData, TrigCoinc);
158 
159  RemoveLateLight(FlashVector, RefinedHitsPerFlash);
160 
161  //checkOnBeamFlash(FlashVector);
162 
163  // Finally, write the association list.
164  // back_inserter tacks the result onto the end of AssocList
165  for (auto& HitIndicesThisFlash : RefinedHitsPerFlash)
166  AssocList.push_back(HitIndicesThisFlash);
167 
168  } // End RunFlashFinder
169 
170  //----------------------------------------------------------------------------
171  unsigned int
172  GetAccumIndex(double const PeakTime,
173  double const MinTime,
174  double const BinWidth,
175  double const BinOffset)
176  {
177  return static_cast<unsigned int>((PeakTime - MinTime + BinOffset) / BinWidth);
178  }
179 
180  //----------------------------------------------------------------------------
181  void
182  FillAccumulator(unsigned int const& AccumIndex,
183  unsigned int const& HitIndex,
184  double const PE,
185  float const FlashThreshold,
186  std::vector<double>& Binned,
187  std::vector<std::vector<int>>& Contributors,
188  std::vector<int>& FlashesInAccumulator)
189  {
190 
191  Contributors.at(AccumIndex).push_back(HitIndex);
192 
193  Binned.at(AccumIndex) += PE;
194 
195  // If this wasn't a flash already, add it to the list
196  if (Binned.at(AccumIndex) >= FlashThreshold && (Binned.at(AccumIndex) - PE) < FlashThreshold)
197  FlashesInAccumulator.push_back(AccumIndex);
198  }
199 
200  //----------------------------------------------------------------------------
201  void
203  std::vector<int> const& FlashesInAccumulator,
204  std::vector<double> const& BinnedPE,
205  int const& Accumulator,
206  std::map<double, std::map<int, std::vector<int>>, std::greater<double>>& FlashesBySize)
207  {
208  for (auto const& flash : FlashesInAccumulator)
209  FlashesBySize[BinnedPE.at(flash)][Accumulator].push_back(flash);
210  }
211 
212  //----------------------------------------------------------------------------
213  void
214  FillHitsThisFlash(std::vector<std::vector<int>> const& Contributors,
215  int const& Bin,
216  std::vector<int> const& HitClaimedByFlash,
217  std::vector<int>& HitsThisFlash)
218  {
219  // For each hit in the flash
220  for (auto const& HitIndex : Contributors.at(Bin))
221  // If unclaimed, claim it
222  if (HitClaimedByFlash.at(HitIndex) == -1) HitsThisFlash.push_back(HitIndex);
223  }
224 
225  //----------------------------------------------------------------------------
226  void
227  ClaimHits(std::vector<recob::OpHit> const& HitVector,
228  std::vector<int> const& HitsThisFlash,
229  float const FlashThreshold,
230  std::vector<std::vector<int>>& HitsPerFlash,
231  std::vector<int>& HitClaimedByFlash)
232  {
233  // Check for newly claimed hits
234  double PE = 0;
235  for (auto const& Hit : HitsThisFlash)
236  PE += HitVector.at(Hit).PE();
237 
238  if (PE < FlashThreshold) return;
239 
240  // Add the flash to the list
241  HitsPerFlash.push_back(HitsThisFlash);
242 
243  // And claim all the hits
244  for (auto const& Hit : HitsThisFlash)
245  if (HitClaimedByFlash.at(Hit) == -1) HitClaimedByFlash.at(Hit) = HitsPerFlash.size() - 1;
246  }
247 
248  //----------------------------------------------------------------------------
249  void
250  AssignHitsToFlash(std::vector<int> const& FlashesInAccumulator1,
251  std::vector<int> const& FlashesInAccumulator2,
252  std::vector<double> const& Binned1,
253  std::vector<double> const& Binned2,
254  std::vector<std::vector<int>> const& Contributors1,
255  std::vector<std::vector<int>> const& Contributors2,
256  std::vector<recob::OpHit> const& HitVector,
257  std::vector<std::vector<int>>& HitsPerFlash,
258  float const FlashThreshold)
259  {
260  // Sort all the flashes found by size. The structure is:
261  // FlashesBySize[flash size][accumulator_num] = [flash_index1, flash_index2...]
262  std::map<double, std::map<int, std::vector<int>>, std::greater<double>> FlashesBySize;
263 
264  // Sort the flashes by size using map
265  FillFlashesBySizeMap(FlashesInAccumulator1, Binned1, 1, FlashesBySize);
266  FillFlashesBySizeMap(FlashesInAccumulator2, Binned2, 2, FlashesBySize);
267 
268  // This keeps track of which hits are claimed by which flash
269  std::vector<int> HitClaimedByFlash(HitVector.size(), -1);
270 
271  // Walk from largest to smallest, claiming hits.
272  // The biggest flash always gets dibbs,
273  // but we keep track of overlaps for re-merging later (do we? ---WK)
274  for (auto const& itFlash : FlashesBySize)
275  // If several with same size, walk through accumulators
276  for (auto const& itAcc : itFlash.second) {
277 
278  int Accumulator = itAcc.first;
279 
280  // Walk through flash-tagged bins in this accumulator
281  for (auto const& Bin : itAcc.second) {
282 
283  std::vector<int> HitsThisFlash;
284 
285  if (Accumulator == 1)
286  FillHitsThisFlash(Contributors1, Bin, HitClaimedByFlash, HitsThisFlash);
287  else if (Accumulator == 2)
288  FillHitsThisFlash(Contributors2, Bin, HitClaimedByFlash, HitsThisFlash);
289 
290  ClaimHits(HitVector, HitsThisFlash, FlashThreshold, HitsPerFlash, HitClaimedByFlash);
291 
292  } // End loop over this accumulator
293 
294  } // End loops over accumulators
295  // End of loops over sorted flashes
296 
297  } // End AssignHitsToFlash
298 
299  //----------------------------------------------------------------------------
300  void
301  FindSeedHit(std::map<double, std::vector<int>, std::greater<double>> const& HitsBySize,
302  std::vector<bool>& HitsUsed,
303  std::vector<recob::OpHit> const& HitVector,
304  std::vector<int>& HitsThisRefinedFlash,
305  double& PEAccumulated,
306  double& FlashMaxTime,
307  double& FlashMinTime)
308  {
309  for (auto const& itHit : HitsBySize)
310  for (auto const& HitID : itHit.second) {
311 
312  if (HitsUsed.at(HitID)) continue;
313 
314  PEAccumulated = HitVector.at(HitID).PE();
315  FlashMaxTime = HitVector.at(HitID).PeakTime() + 0.5 * HitVector.at(HitID).Width();
316  FlashMinTime = HitVector.at(HitID).PeakTime() - 0.5 * HitVector.at(HitID).Width();
317 
318  HitsThisRefinedFlash.clear();
319  HitsThisRefinedFlash.push_back(HitID);
320 
321  HitsUsed.at(HitID) = true;
322  return;
323 
324  } // End loop over inner vector
325  // End loop over HitsBySize map
326 
327  } // End FindSeedHit
328 
329  //----------------------------------------------------------------------------
330  void
331  AddHitToFlash(int const& HitID,
332  std::vector<bool>& HitsUsed,
333  recob::OpHit const& currentHit,
334  double const WidthTolerance,
335  std::vector<int>& HitsThisRefinedFlash,
336  double& PEAccumulated,
337  double& FlashMaxTime,
338  double& FlashMinTime)
339  {
340  if (HitsUsed.at(HitID)) return;
341 
342  double HitTime = currentHit.PeakTime();
343  double HitWidth = 0.5 * currentHit.Width();
344  double FlashTime = 0.5 * (FlashMaxTime + FlashMinTime);
345  double FlashWidth = 0.5 * (FlashMaxTime - FlashMinTime);
346 
347  if (std::abs(HitTime - FlashTime) > WidthTolerance * (HitWidth + FlashWidth)) return;
348 
349  HitsThisRefinedFlash.push_back(HitID);
350  FlashMaxTime = std::max(FlashMaxTime, HitTime + HitWidth);
351  FlashMinTime = std::min(FlashMinTime, HitTime - HitWidth);
352  PEAccumulated += currentHit.PE();
353  HitsUsed[HitID] = true;
354 
355  } // End AddHitToFlash
356 
357  //----------------------------------------------------------------------------
358  void
359  CheckAndStoreFlash(std::vector<std::vector<int>>& RefinedHitsPerFlash,
360  std::vector<int> const& HitsThisRefinedFlash,
361  double const PEAccumulated,
362  float const FlashThreshold,
363  std::vector<bool>& HitsUsed)
364  {
365  // If above threshold, we just add hits to the flash vector, and move on
366  if (PEAccumulated >= FlashThreshold) {
367  RefinedHitsPerFlash.push_back(HitsThisRefinedFlash);
368  return;
369  }
370 
371  // If there is only one hit in collection, we can immediately move on
372  if (HitsThisRefinedFlash.size() == 1) return;
373 
374  // We need to release all other hits (allow possible reuse)
375  for (std::vector<int>::const_iterator hitIterator = std::next(HitsThisRefinedFlash.begin());
376  hitIterator != HitsThisRefinedFlash.end();
377  ++hitIterator)
378  HitsUsed.at(*hitIterator) = false;
379 
380  } // End CheckAndStoreFlash
381 
382  //----------------------------------------------------------------------------
383  void
384  RefineHitsInFlash(std::vector<int> const& HitsThisFlash,
385  std::vector<recob::OpHit> const& HitVector,
386  std::vector<std::vector<int>>& RefinedHitsPerFlash,
387  float const WidthTolerance,
388  float const FlashThreshold)
389  {
390  // Sort the hits by their size using map
391  // HitsBySize[HitSize] = [hit1, hit2 ...]
392  std::map<double, std::vector<int>, std::greater<double>> HitsBySize;
393  for (auto const& HitID : HitsThisFlash)
394  HitsBySize[HitVector.at(HitID).PE()].push_back(HitID);
395 
396  // Heres what we do:
397  // 1.Start with the biggest remaining hit
398  // 2.Look for any within one width of this hit
399  // 3.Find the new upper and lower bounds of the flash
400  // 4.Collect again
401  // 5.Repeat until no new hits collected
402  // 6.Remove these hits from consideration and repeat
403 
404  std::vector<bool> HitsUsed(HitVector.size(), false);
405  double PEAccumulated, FlashMaxTime, FlashMinTime;
406  std::vector<int> HitsThisRefinedFlash;
407 
408  while (true) {
409 
410  HitsThisRefinedFlash.clear();
411  PEAccumulated = 0;
412  FlashMaxTime = 0;
413  FlashMinTime = 0;
414 
415  FindSeedHit(HitsBySize,
416  HitsUsed,
417  HitVector,
418  HitsThisRefinedFlash,
419  PEAccumulated,
420  FlashMaxTime,
421  FlashMinTime);
422 
423  if (HitsThisRefinedFlash.size() == 0) return;
424 
425  // Start this at zero to do the while at least once
426  size_t NHitsThisRefinedFlash = 0;
427 
428  // If size of HitsThisRefinedFlash is same size,
429  // that means we're not adding anymore
430  while (NHitsThisRefinedFlash < HitsThisRefinedFlash.size()) {
431  NHitsThisRefinedFlash = HitsThisRefinedFlash.size();
432 
433  for (auto const& itHit : HitsBySize)
434  for (auto const& HitID : itHit.second)
435  AddHitToFlash(HitID,
436  HitsUsed,
437  HitVector.at(HitID),
439  HitsThisRefinedFlash,
440  PEAccumulated,
441  FlashMaxTime,
442  FlashMinTime);
443  }
444 
445  // We did our collecting, now check if the flash is
446  // still good and push back
448  RefinedHitsPerFlash, HitsThisRefinedFlash, PEAccumulated, FlashThreshold, HitsUsed);
449 
450  } // End while there are hits left
451 
452  } // End RefineHitsInFlash
453 
454  //----------------------------------------------------------------------------
455  void
456  AddHitContribution(recob::OpHit const& currentHit,
457  double& MaxTime,
458  double& MinTime,
459  double& AveTime,
460  double& FastToTotal,
461  double& AveAbsTime,
462  double& TotalPE,
463  std::vector<double>& PEs)
464  {
465  double PEThisHit = currentHit.PE();
466  double TimeThisHit = currentHit.PeakTime();
467  if (TimeThisHit > MaxTime) MaxTime = TimeThisHit;
468  if (TimeThisHit < MinTime) MinTime = TimeThisHit;
469 
470  // These quantities for the flash are defined
471  // as the weighted averages over the hits
472  AveTime += PEThisHit * TimeThisHit;
473  FastToTotal += PEThisHit * currentHit.FastToTotal();
474  AveAbsTime += PEThisHit * currentHit.PeakTimeAbs();
475 
476  // These are totals
477  TotalPE += PEThisHit;
478  PEs.at(static_cast<unsigned int>(currentHit.OpChannel())) += PEThisHit;
479  }
480 
481  //----------------------------------------------------------------------------
482  void
483  GetHitGeometryInfo(recob::OpHit const& currentHit,
484  geo::GeometryCore const& geom,
485  std::vector<double>& sumw,
486  std::vector<double>& sumw2,
487  double& sumy,
488  double& sumy2,
489  double& sumz,
490  double& sumz2)
491  {
492  double xyz[3];
493  geom.OpDetGeoFromOpChannel(currentHit.OpChannel()).GetCenter(xyz);
494  double PEThisHit = currentHit.PE();
495 
496  geo::TPCID tpc = geom.FindTPCAtPosition(xyz);
497  // if the point does not fall into any TPC,
498  // it does not contribute to the average wire position
499  if (tpc.isValid) {
500  for (size_t p = 0; p != geom.Nplanes(); ++p) {
501  geo::PlaneID const planeID(tpc, p);
502  unsigned int w = geom.NearestWire(xyz, planeID);
503  sumw.at(p) += PEThisHit * w;
504  sumw2.at(p) += PEThisHit * w * w;
505  }
506  } // if we found the TPC
507  sumy += PEThisHit * xyz[1];
508  sumy2 += PEThisHit * xyz[1] * xyz[1];
509  sumz += PEThisHit * xyz[2];
510  sumz2 += PEThisHit * xyz[2] * xyz[2];
511  }
512 
513  //----------------------------------------------------------------------------
514  double
515  CalculateWidth(double const sum, double const sum_squared, double const weights_sum)
516  {
517  if (sum_squared * weights_sum - sum * sum < 0)
518  return 0;
519  else
520  return std::sqrt(sum_squared * weights_sum - sum * sum) / weights_sum;
521  }
522 
523  //----------------------------------------------------------------------------
524  void
525  ConstructFlash(std::vector<int> const& HitsPerFlashVec,
526  std::vector<recob::OpHit> const& HitVector,
527  std::vector<recob::OpFlash>& FlashVector,
528  geo::GeometryCore const& geom,
529  detinfo::DetectorClocksData const& ClocksData,
530  float const TrigCoinc)
531  {
532  double MaxTime = -std::numeric_limits<double>::max();
533  double MinTime = std::numeric_limits<double>::max();
534 
535  std::vector<double> PEs(geom.MaxOpChannel() + 1, 0.0);
536  unsigned int Nplanes = geom.Nplanes();
537  std::vector<double> sumw(Nplanes, 0.0);
538  std::vector<double> sumw2(Nplanes, 0.0);
539 
540  double TotalPE = 0;
541  double AveTime = 0;
542  double AveAbsTime = 0;
543  double FastToTotal = 0;
544  double sumy = 0;
545  double sumz = 0;
546  double sumy2 = 0;
547  double sumz2 = 0;
548 
549  for (auto const& HitID : HitsPerFlashVec) {
551  HitVector.at(HitID), MaxTime, MinTime, AveTime, FastToTotal, AveAbsTime, TotalPE, PEs);
552  GetHitGeometryInfo(HitVector.at(HitID), geom, sumw, sumw2, sumy, sumy2, sumz, sumz2);
553  }
554 
555  AveTime /= TotalPE;
556  AveAbsTime /= TotalPE;
557  FastToTotal /= TotalPE;
558 
559  double meany = sumy / TotalPE;
560  double meanz = sumz / TotalPE;
561 
562  double widthy = CalculateWidth(sumy, sumy2, TotalPE);
563  double widthz = CalculateWidth(sumz, sumz2, TotalPE);
564 
565  std::vector<double> WireCenters(Nplanes, 0.0);
566  std::vector<double> WireWidths(Nplanes, 0.0);
567 
568  for (size_t p = 0; p != Nplanes; ++p) {
569  WireCenters.at(p) = sumw.at(p) / TotalPE;
570  WireWidths.at(p) = CalculateWidth(sumw.at(p), sumw2.at(p), TotalPE);
571  }
572 
573  // Emprical corrections to get the Frame right.
574  // Eventual solution - remove frames
575  int Frame = ClocksData.OpticalClock().Frame(AveAbsTime - 18.1);
576  if (Frame == 0) Frame = 1;
577 
578  int BeamFrame = ClocksData.OpticalClock().Frame(ClocksData.TriggerTime());
579  bool InBeamFrame = false;
580  if (!(ClocksData.TriggerTime() < 0)) InBeamFrame = (Frame == BeamFrame);
581 
582  double TimeWidth = (MaxTime - MinTime) / 2.0;
583 
584  int OnBeamTime = 0;
585  if (InBeamFrame && (std::abs(AveTime) < TrigCoinc)) OnBeamTime = 1;
586 
587  FlashVector.emplace_back(AveTime,
588  TimeWidth,
589  AveAbsTime,
590  Frame,
591  PEs,
592  InBeamFrame,
593  OnBeamTime,
594  FastToTotal,
595  meany,
596  widthy,
597  meanz,
598  widthz,
599  WireCenters,
600  WireWidths);
601  }
602 
603  //----------------------------------------------------------------------------
604  double
605  GetLikelihoodLateLight(double const iPE,
606  double const iTime,
607  double const iWidth,
608  double const jPE,
609  double const jTime,
610  double const jWidth)
611  {
612  if (iTime > jTime) return 1e6;
613 
614  // Calculate hypothetical PE if this were actually a late flash from i.
615  // Argon time const is 1600 ns, so 1.6.
616  double HypPE = iPE * jWidth / iWidth * std::exp(-(jTime - iTime) / 1.6);
617  double nsigma = (jPE - HypPE) / std::sqrt(HypPE);
618  return nsigma;
619  }
620 
621  //----------------------------------------------------------------------------
622  void
623  MarkFlashesForRemoval(std::vector<recob::OpFlash> const& FlashVector,
624  size_t const BeginFlash,
625  std::vector<bool>& MarkedForRemoval)
626  {
627  for (size_t iFlash = BeginFlash; iFlash != FlashVector.size(); ++iFlash) {
628 
629  double iTime = FlashVector.at(iFlash).Time();
630  double iPE = FlashVector.at(iFlash).TotalPE();
631  double iWidth = FlashVector.at(iFlash).TimeWidth();
632 
633  for (size_t jFlash = iFlash + 1; jFlash != FlashVector.size(); ++jFlash) {
634 
635  if (MarkedForRemoval.at(jFlash - BeginFlash)) continue;
636 
637  double jTime = FlashVector.at(jFlash).Time();
638  double jPE = FlashVector.at(jFlash).TotalPE();
639  double jWidth = FlashVector.at(jFlash).TimeWidth();
640 
641  // If smaller than, or within 2sigma of expectation,
642  // attribute to late light and toss out
643  if (GetLikelihoodLateLight(iPE, iTime, iWidth, jPE, jTime, jWidth) < 3.0)
644  MarkedForRemoval.at(jFlash - BeginFlash) = true;
645  }
646  }
647  }
648 
649  //----------------------------------------------------------------------------
650  void
651  RemoveFlashesFromVectors(std::vector<bool> const& MarkedForRemoval,
652  std::vector<recob::OpFlash>& FlashVector,
653  size_t const BeginFlash,
654  std::vector<std::vector<int>>& RefinedHitsPerFlash)
655  {
656  for (int iFlash = MarkedForRemoval.size() - 1; iFlash != -1; --iFlash)
657  if (MarkedForRemoval.at(iFlash)) {
658  RefinedHitsPerFlash.erase(RefinedHitsPerFlash.begin() + iFlash);
659  FlashVector.erase(FlashVector.begin() + BeginFlash + iFlash);
660  }
661  }
662 
663  //----------------------------------------------------------------------------
664  void
665  RemoveLateLight(std::vector<recob::OpFlash>& FlashVector,
666  std::vector<std::vector<int>>& RefinedHitsPerFlash)
667  {
668  std::vector<bool> MarkedForRemoval(RefinedHitsPerFlash.size(), false);
669 
670  size_t const BeginFlash = FlashVector.size() - RefinedHitsPerFlash.size();
671 
672  recob::OpFlashSortByTime sort_flash_by_time;
673 
674  // Determine the sort of FlashVector starting at BeginFlash
675  auto sort_order = sort_permutation(FlashVector, BeginFlash, sort_flash_by_time);
676 
677  // Sort the RefinedHitsPerFlash in the same way as tail end of FlashVector
678  apply_permutation(RefinedHitsPerFlash, sort_order);
679 
680  std::sort(FlashVector.begin() + BeginFlash, FlashVector.end(), sort_flash_by_time);
681 
682  MarkFlashesForRemoval(FlashVector, BeginFlash, MarkedForRemoval);
683 
684  RemoveFlashesFromVectors(MarkedForRemoval, FlashVector, BeginFlash, RefinedHitsPerFlash);
685 
686  } // End RemoveLateLight
687 
688  //----------------------------------------------------------------------------
689  template <typename T, typename Compare>
690  std::vector<int>
691  sort_permutation(std::vector<T> const& vec, int offset, Compare compare)
692  {
693 
694  std::vector<int> p(vec.size() - offset);
695  std::iota(p.begin(), p.end(), 0);
696  std::sort(
697  p.begin(), p.end(), [&](int i, int j) { return compare(vec[i + offset], vec[j + offset]); });
698  return p;
699  }
700 
701  //----------------------------------------------------------------------------
702  template <typename T>
703  void
704  apply_permutation(std::vector<T>& vec, std::vector<int> const& p)
705  {
706 
707  std::vector<T> sorted_vec(p.size());
708  std::transform(p.begin(), p.end(), sorted_vec.begin(), [&](int i) { return vec[i]; });
709  vec = sorted_vec;
710  }
711 
712 } // End namespace opdet
void FillHitsThisFlash(std::vector< std::vector< int >> const &Contributors, int const &Bin, std::vector< int > const &HitClaimedByFlash, std::vector< int > &HitsThisFlash)
Definition: OpFlashAlg.cxx:214
double FastToTotal() const
Definition: OpHit.h:96
BEGIN_PROLOG TPC Trig offset(g4 rise time) ProjectToHeight
Definition: CORSIKAGen.fcl:7
void CheckAndStoreFlash(std::vector< std::vector< int >> &RefinedHitsPerFlash, std::vector< int > const &HitsThisRefinedFlash, double const PEAccumulated, float const FlashThreshold, std::vector< bool > &HitsUsed)
Definition: OpFlashAlg.cxx:359
static constexpr Sample_t transform(Sample_t sample)
void RunFlashFinder(std::vector< recob::OpHit > const &HitVector, std::vector< recob::OpFlash > &FlashVector, std::vector< std::vector< int >> &AssocList, double const BinWidth, geo::GeometryCore const &geom, float const FlashThreshold, float const WidthTolerance, detinfo::DetectorClocksData const &ClocksData, float const TrigCoinc)
Definition: OpFlashAlg.cxx:63
void ConstructFlash(std::vector< int > const &HitsPerFlashVec, std::vector< recob::OpHit > const &HitVector, std::vector< recob::OpFlash > &FlashVector, geo::GeometryCore const &geom, detinfo::DetectorClocksData const &ClocksData, float const TrigCoinc)
Definition: OpFlashAlg.cxx:525
pdgs p
Definition: selectors.fcl:22
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
bool isValid
Whether this ID points to a valid element.
Definition: geo_types.h:211
void AddHitContribution(recob::OpHit const &currentHit, double &MaxTime, double &MinTime, double &AveTime, double &FastToTotal, double &AveAbsTime, double &TotalPE, std::vector< double > &PEs)
Definition: OpFlashAlg.cxx:456
double PeakTime() const
Definition: OpHit.h:88
void apply_permutation(std::vector< T > &vec, std::vector< int > const &p)
Definition: OpFlashAlg.cxx:704
constexpr int Frame() const noexcept
Returns the number of the frame containing the clock current time.
Definition: ElecClock.h:304
process_name hit
Definition: cheaterreco.fcl:51
void AssignHitsToFlash(std::vector< int > const &FlashesInAccumulator1, std::vector< int > const &FlashesInAccumulator2, std::vector< double > const &Binned1, std::vector< double > const &Binned2, std::vector< std::vector< int >> const &Contributors1, std::vector< std::vector< int >> const &Contributors2, std::vector< recob::OpHit > const &HitVector, std::vector< std::vector< int >> &HitsPerFlash, float const FlashThreshold)
Definition: OpFlashAlg.cxx:250
pure virtual base interface for detector clocks
std::array< float, 2 > HitVector(const recob::Hit &hit, const geo::GeometryCore *geo, const detinfo::DetectorPropertiesData &dprop)
bool Compare(const T &a, const T &b, const std::string &key)
Definition: diff_spectra.cc:93
void FindSeedHit(std::map< double, std::vector< int >, std::greater< double >> const &HitsBySize, std::vector< bool > &HitsUsed, std::vector< recob::OpHit > const &HitVector, std::vector< int > &HitsThisRefinedFlash, double &PEAccumulated, double &FlashMaxTime, double &FlashMinTime)
Definition: OpFlashAlg.cxx:301
geo::TPCID FindTPCAtPosition(double const worldLoc[3]) const
Returns the ID of the TPC at specified location.
auto vector(Vector const &v)
Returns a manipulator which will print the specified array.
Definition: DumpUtils.h:265
Access the description of detector geometry.
T abs(T value)
unsigned int Nplanes(unsigned int tpc=0, unsigned int cstat=0) const
Returns the total number of wire planes in the specified TPC.
void MarkFlashesForRemoval(std::vector< recob::OpFlash > const &FlashVector, size_t const BeginFlash, std::vector< bool > &MarkedForRemoval)
Definition: OpFlashAlg.cxx:623
double CalculateWidth(double const sum, double const sum_squared, double const weights_sum)
Definition: OpFlashAlg.cxx:515
double Width() const
Definition: OpHit.h:92
void ClaimHits(std::vector< recob::OpHit > const &HitVector, std::vector< int > const &HitsThisFlash, float const FlashThreshold, std::vector< std::vector< int >> &HitsPerFlash, std::vector< int > &HitClaimedByFlash)
Definition: OpFlashAlg.cxx:227
constexpr float FlashThreshold
geo::WireID::WireID_t NearestWire(geo::Point_t const &point, geo::PlaneID const &planeid) const
Returns the index of wire closest to position in the specified TPC.
std::vector< int > sort_permutation(std::vector< T > const &vec, int offset, Compare compare)
Definition: OpFlashAlg.cxx:691
void checkOnBeamFlash(std::vector< recob::OpFlash > const &FlashVector)
Definition: OpFlashAlg.cxx:54
unsigned int MaxOpChannel() const
Largest optical channel number.
void FillFlashesBySizeMap(std::vector< int > const &FlashesInAccumulator, std::vector< double > const &BinnedPE, int const &Accumulator, std::map< double, std::map< int, std::vector< int >>, std::greater< double >> &FlashesBySize)
Definition: OpFlashAlg.cxx:202
void RemoveLateLight(std::vector< recob::OpFlash > &FlashVector, std::vector< std::vector< int >> &RefinedHitsPerFlash)
Definition: OpFlashAlg.cxx:665
void writeHistogram(std::vector< double > const &binned)
Definition: OpFlashAlg.cxx:35
The data type to uniquely identify a TPC.
Definition: geo_types.h:386
Description of geometry of one entire detector.
Definition of data types for geometry description.
double TriggerTime() const
Trigger electronics clock time in [us].
ElecClock const & OpticalClock() const noexcept
Borrow a const Optical clock with time set to Trigger time [us].
double PE() const
Definition: OpHit.h:95
void AddHitToFlash(int const &HitID, std::vector< bool > &HitsUsed, recob::OpHit const &currentHit, double const WidthTolerance, std::vector< int > &HitsThisRefinedFlash, double &PEAccumulated, double &FlashMaxTime, double &FlashMinTime)
Definition: OpFlashAlg.cxx:331
Encapsulate the geometry of an optical detector.
void RefineHitsInFlash(std::vector< int > const &HitsThisFlash, std::vector< recob::OpHit > const &HitVector, std::vector< std::vector< int >> &RefinedHitsPerFlash, float const WidthTolerance, float const FlashThreshold)
Definition: OpFlashAlg.cxx:384
Contains all timing reference information for the detector.
unsigned int GetAccumIndex(double const PeakTime, double const MinTime, double const BinWidth, double const BinOffset)
Definition: OpFlashAlg.cxx:172
double PeakTimeAbs() const
Definition: OpHit.h:89
Class def header for a class ElecClock.
constexpr double WidthTolerance
void GetHitGeometryInfo(recob::OpHit const &currentHit, geo::GeometryCore const &geom, std::vector< double > &sumw, std::vector< double > &sumw2, double &sumy, double &sumy2, double &sumz, double &sumz2)
Definition: OpFlashAlg.cxx:483
void RemoveFlashesFromVectors(std::vector< bool > const &MarkedForRemoval, std::vector< recob::OpFlash > &FlashVector, size_t const BeginFlash, std::vector< std::vector< int >> &RefinedHitsPerFlash)
Definition: OpFlashAlg.cxx:651
OpDetGeo const & OpDetGeoFromOpChannel(unsigned int OpChannel) const
Returns the geo::OpDetGeo object for the given channel number.
int OpChannel() const
Definition: OpHit.h:86
void FillAccumulator(unsigned int const &AccumIndex, unsigned int const &HitIndex, double const PE, float const FlashThreshold, std::vector< double > &Binned, std::vector< std::vector< int >> &Contributors, std::vector< int > &FlashesInAccumulator)
Definition: OpFlashAlg.cxx:182
BEGIN_PROLOG could also be cout
double GetLikelihoodLateLight(double const iPE, double const iTime, double const iWidth, double const jPE, double const jTime, double const jWidth)
Definition: OpFlashAlg.cxx:605