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