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