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