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