LArSoft  v10_04_05
Liquid Argon Software toolkit - https://larsoft.org/
GausHitFinder_module.cc
Go to the documentation of this file.
1 //
3 // GaussHitFinder class
4 //
5 // jaasaadi@syr.edu
6 //
7 // This algorithm is designed to find hits on wires after deconvolution.
8 // -----------------------------------
9 // This algorithm is based on the FFTHitFinder written by Brian Page,
10 // Michigan State University, for the ArgoNeuT experiment.
11 //
12 //
13 // The algorithm walks along the wire and looks for pulses above threshold
14 // The algorithm then attempts to fit n-gaussians to these pulses where n
15 // is set by the number of peaks found in the pulse
16 // If the Chi2/NDF returned is "bad" it attempts to fit n+1 gaussians to
17 // the pulse. If this is a better fit it then uses the parameters of the
18 // Gaussian fit to characterize the "hit" object
19 //
20 // To use this simply include the following in your producers:
21 // gaushit: @local::microboone_gaushitfinder
22 // gaushit: @local::argoneut_gaushitfinder
24 
25 // C/C++ standard library
26 #include <algorithm> // std::accumulate()
27 #include <atomic>
28 #include <memory> // std::unique_ptr()
29 #include <string>
30 #include <utility> // std::move()
31 
32 // Framework includes
37 #include "art/Utilities/Globals.h"
39 #include "art_root_io/TFileService.h"
41 #include "fhiclcpp/ParameterSet.h"
42 
43 // LArSoft Includes
45 #include "larcoreobj/SimpleTypesAndConstants/RawTypes.h" // raw::ChannelID_t
50 
53 
54 // ROOT Includes
55 #include "TH1F.h"
56 #include "TMath.h"
57 
58 #include "tbb/concurrent_vector.h"
59 #include "tbb/parallel_for.h"
60 
61 namespace hit {
63  public:
64  explicit GausHitFinder(fhicl::ParameterSet const& pset, art::ProcessingFrame const&);
65 
66  private:
67  void produce(art::Event& evt, art::ProcessingFrame const&) override;
68  void beginJob(art::ProcessingFrame const&) override;
69 
70  std::vector<double> FillOutHitParameterVector(const std::vector<double>& input);
71 
72  const bool fFilterHits;
73  const bool fFillHists;
74 
75  const std::string fCalDataModuleLabel;
76  const std::string fAllHitsInstanceName;
77 
78  const std::vector<int> fLongMaxHitsVec;
79  const std::vector<int> fLongPulseWidthVec;
80 
81  const size_t fMaxMultiHit;
82  const int fAreaMethod;
83  const std::vector<double>
85  const double fChi2NDF;
86 
87  const std::vector<float> fPulseHeightCuts;
88  const std::vector<float> fPulseWidthCuts;
89  const std::vector<float> fPulseRatioCuts;
90 
91  std::atomic<size_t> fEventCount{0};
92 
93  //only Standard and Morphological implementation is threadsafe.
94  std::vector<std::unique_ptr<reco_tool::ICandidateHitFinder>>
96  // only Marqdt implementation is threadsafe.
97  std::unique_ptr<reco_tool::IPeakFitter> fPeakFitterTool;
98  //HitFilterAlg implementation is threadsafe.
99  std::unique_ptr<HitFilterAlg> fHitFilterAlg;
100 
101  //only used when fFillHists is true and in single threaded mode.
102  TH1F* fFirstChi2;
103  TH1F* fChi2;
104 
105  }; // class GausHitFinder
106 
107  //-------------------------------------------------
108  //-------------------------------------------------
110  : SharedProducer{pset}
111  , fFilterHits(pset.get<bool>("FilterHits", false))
112  , fFillHists(pset.get<bool>("FillHists", false))
113  , fCalDataModuleLabel(pset.get<std::string>("CalDataModuleLabel"))
114  , fAllHitsInstanceName(pset.get<std::string>("AllHitsInstanceName", ""))
115  , fLongMaxHitsVec(pset.get<std::vector<int>>("LongMaxHits", std::vector<int>() = {25, 25, 25}))
117  pset.get<std::vector<int>>("LongPulseWidth", std::vector<int>() = {16, 16, 16}))
118  , fMaxMultiHit(pset.get<int>("MaxMultiHit"))
119  , fAreaMethod(pset.get<int>("AreaMethod"))
120  , fAreaNormsVec(FillOutHitParameterVector(pset.get<std::vector<double>>("AreaNorms")))
121  , fChi2NDF(pset.get<double>("Chi2NDF"))
123  pset.get<std::vector<float>>("PulseHeightCuts", std::vector<float>() = {3.0, 3.0, 3.0}))
124  , fPulseWidthCuts(
125  pset.get<std::vector<float>>("PulseWidthCuts", std::vector<float>() = {2.0, 1.5, 1.0}))
126  , fPulseRatioCuts(
127  pset.get<std::vector<float>>("PulseRatioCuts", std::vector<float>() = {0.35, 0.40, 0.20}))
128  {
129  if (fFillHists && art::Globals::instance()->nthreads() > 1u) {
131  << "Cannot fill histograms when multiple threads configured, please set fFillHists to "
132  "false or change number of threads to 1\n";
133  }
134  async<art::InEvent>();
135  if (fFilterHits) {
136  fHitFilterAlg = std::make_unique<HitFilterAlg>(pset.get<fhicl::ParameterSet>("HitFilterAlg"));
137  }
138 
139  // recover the tool to do the candidate hit finding
140  // Recover the vector of fhicl parameters for the ROI tools
141  const fhicl::ParameterSet& hitFinderTools = pset.get<fhicl::ParameterSet>("HitFinderToolVec");
142 
143  fHitFinderToolVec.resize(hitFinderTools.get_pset_names().size());
144 
145  for (const std::string& hitFinderTool : hitFinderTools.get_pset_names()) {
146  const fhicl::ParameterSet& hitFinderToolParamSet =
147  hitFinderTools.get<fhicl::ParameterSet>(hitFinderTool);
148  size_t planeIdx = hitFinderToolParamSet.get<size_t>("Plane");
149 
150  fHitFinderToolVec.at(planeIdx) =
151  art::make_tool<reco_tool::ICandidateHitFinder>(hitFinderToolParamSet);
152  }
153 
154  // Recover the peak fitting tool
156  art::make_tool<reco_tool::IPeakFitter>(pset.get<fhicl::ParameterSet>("PeakFitter"));
157 
158  // let HitCollectionCreator declare that we are going to produce
159  // hits and associations with wires and raw digits
160  // We want the option to output two hit collections, one filtered
161  // and one with all hits. The key to doing this will be a non-null
162  // instance name for the second collection
163  // (with no particular product label)
165  producesCollector(), fAllHitsInstanceName, true, false); //fMakeRawDigitAssns);
166 
167  // and now the filtered hits...
168  if (fAllHitsInstanceName != "")
170  producesCollector(), "", true, false); //fMakeRawDigitAssns);
171 
172  return;
173  } // GausHitFinder::GausHitFinder()
174 
175  //-------------------------------------------------
176  //-------------------------------------------------
177  std::vector<double> GausHitFinder::FillOutHitParameterVector(const std::vector<double>& input)
178  {
179  if (input.size() == 0)
180  throw std::runtime_error(
181  "GausHitFinder::FillOutHitParameterVector ERROR! Input config vector has zero size.");
182 
183  std::vector<double> output;
184  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout const>()->Get();
185  const unsigned int N_PLANES = wireReadoutGeom.Nplanes();
186 
187  if (input.size() == 1)
188  output.resize(N_PLANES, input[0]);
189  else if (input.size() == N_PLANES)
190  output = input;
191  else
192  throw std::runtime_error("GausHitFinder::FillOutHitParameterVector ERROR! Input config "
193  "vector size !=1 and !=N_PLANES.");
194  return output;
195  }
196 
197  //-------------------------------------------------
198  //-------------------------------------------------
200  {
201  // get access to the TFile service
203 
204  // ======================================
205  // === Hit Information for Histograms ===
206  if (fFillHists) {
207  fFirstChi2 = tfs->make<TH1F>("fFirstChi2", "#chi^{2}", 10000, 0, 5000);
208  fChi2 = tfs->make<TH1F>("fChi2", "#chi^{2}", 10000, 0, 5000);
209  }
210  }
211 
212  // This algorithm uses the fact that deconvolved signals are very smooth
213  // and looks for hits as areas between local minima that have signal above
214  // threshold.
215  //-------------------------------------------------
217  {
218  unsigned int count = fEventCount.fetch_add(1);
219  //==================================================================================================
220 
221  TH1::AddDirectory(kFALSE);
222 
223  auto const& wireReadoutGeom = art::ServiceHandle<geo::WireReadout const>()->Get();
224 
225  // ###############################################
226  // ### Making a ptr vector to put on the event ###
227  // ###############################################
228  // this contains the hit collection
229  // and its associations to wires and raw digits
230  recob::HitCollectionCreator allHitCol(evt, fAllHitsInstanceName, true, false);
231 
232  // Handle the filtered hits collection...
233  recob::HitCollectionCreator hcol(evt, "", true, false);
234  recob::HitCollectionCreator* filteredHitCol = 0;
235 
236  if (fFilterHits) filteredHitCol = &hcol;
237 
238  //store in a thread safe way
239  struct hitstruct {
240  recob::Hit hit_tbb;
241  art::Ptr<recob::Wire> wire_tbb;
242  };
243 
244  tbb::concurrent_vector<hitstruct> hitstruct_vec;
245  tbb::concurrent_vector<hitstruct> filthitstruct_vec;
246 
247  // ##########################################
248  // ### Reading in the Wire List object(s) ###
249  // ##########################################
251  evt.getByLabel(fCalDataModuleLabel, wireVecHandle);
252 
253  //#################################################
254  //### Set the charge determination method ###
255  //### Default is to compute the normalized area ###
256  //#################################################
257  std::function<double(double, double, double, double, int, int)> chargeFunc =
258  [](double /* peakMean */,
259  double peakAmp,
260  double peakWidth,
261  double areaNorm,
262  int /* low */,
263  int /* hi */) { return std::sqrt(2 * TMath::Pi()) * peakAmp * peakWidth / areaNorm; };
264 
265  //##############################################
266  //### Alternative is to integrate over pulse ###
267  //##############################################
268  if (fAreaMethod == 0)
269  chargeFunc = [](double peakMean,
270  double peakAmp,
271  double peakWidth,
272  double /* areaNorm */,
273  int low,
274  int hi) {
275  double charge(0);
276  for (int sigPos = low; sigPos < hi; sigPos++)
277  charge += peakAmp * TMath::Gaus(sigPos, peakMean, peakWidth);
278  return charge;
279  };
280 
281  //##############################
282  //### Looping over the wires ###
283  //##############################
284  tbb::parallel_for(
285  static_cast<std::size_t>(0),
286  wireVecHandle->size(),
287  [&](size_t& wireIter) {
288  // ####################################
289  // ### Getting this particular wire ###
290  // ####################################
291  art::Ptr<recob::Wire> wire(wireVecHandle, wireIter);
292 
293  // --- Setting Channel Number and Signal type ---
294 
295  raw::ChannelID_t channel = wire->Channel();
296 
297  // get the WireID for this hit
298  std::vector<geo::WireID> wids = wireReadoutGeom.ChannelToWire(channel);
299  // for now, just take the first option returned from ChannelToWire
300  geo::WireID wid = wids[0];
301  // We need to know the plane to look up parameters
302  geo::PlaneID::PlaneID_t plane = wid.Plane;
303 
304  // ----------------------------------------------------------
305  // -- Setting the appropriate signal widths and thresholds --
306  // -- for the right plane. --
307  // ----------------------------------------------------------
308 
309  // #################################################
310  // ### Set up to loop over ROI's for this wire ###
311  // #################################################
312  const recob::Wire::RegionsOfInterest_t& signalROI = wire->SignalROI();
313 
314  tbb::parallel_for(
315  static_cast<std::size_t>(0),
316  signalROI.n_ranges(),
317  [&](size_t& rangeIter) {
318  const auto& range = signalROI.range(rangeIter);
319  // ROI start time
320  raw::TDCtick_t roiFirstBinTick = range.begin_index();
321 
322  // ###########################################################
323  // ### Scan the waveform and find candidate peaks + merge ###
324  // ###########################################################
325 
328 
329  fHitFinderToolVec.at(plane)->findHitCandidates(
330  range, 0, channel, count, hitCandidateVec);
331  fHitFinderToolVec.at(plane)->MergeHitCandidates(
332  range, hitCandidateVec, mergedCandidateHitVec);
333 
334  // #######################################################
335  // ### Lets loop over the pulses we found on this wire ###
336  // #######################################################
337 
338  for (auto& mergedCands : mergedCandidateHitVec) {
339  int startT = mergedCands.front().startTick;
340  int endT = mergedCands.back().stopTick;
341 
342  // ### Putting in a protection in case things went wrong ###
343  // ### In the end, this primarily catches the case where ###
344  // ### a fake pulse is at the start of the ROI ###
345  if (endT - startT < 5) continue;
346 
347  // #######################################################
348  // ### Clearing the parameter vector for the new Pulse ###
349  // #######################################################
350 
351  // === Setting The Number Of Gaussians to try ===
352  int nGausForFit = mergedCands.size();
353 
354  // ##################################################
355  // ### Calling the function for fitting Gaussians ###
356  // ##################################################
357  double chi2PerNDF(0.);
358  int NDF(1);
359  /*stand alone
360  reco_tool::IPeakFitter::PeakParamsVec peakParamsVec(nGausForFit);
361  */
363 
364  // #######################################################
365  // ### If # requested Gaussians is too large then punt ###
366  // #######################################################
367  if (mergedCands.size() <= fMaxMultiHit) {
368  fPeakFitterTool->findPeakParameters(
369  range.data(), mergedCands, peakParamsVec, chi2PerNDF, NDF);
370 
371  // If the chi2 is infinite then there is a real problem so we bail
372  if (!(chi2PerNDF < std::numeric_limits<double>::infinity())) {
373  chi2PerNDF = 2. * fChi2NDF;
374  NDF = 2;
375  }
376 
377  if (fFillHists) fFirstChi2->Fill(chi2PerNDF);
378  }
379 
380  // #######################################################
381  // ### If too large then force alternate solution ###
382  // ### - Make n hits from pulse train where n will ###
383  // ### depend on the fhicl parameter fLongPulseWidth ###
384  // ### Also do this if chi^2 is too large ###
385  // #######################################################
386  if (mergedCands.size() > fMaxMultiHit || nGausForFit * chi2PerNDF > fChi2NDF) {
387  int longPulseWidth = fLongPulseWidthVec.at(plane);
388  int nHitsThisPulse = (endT - startT) / longPulseWidth;
389 
390  if (nHitsThisPulse > fLongMaxHitsVec.at(plane)) {
391  nHitsThisPulse = fLongMaxHitsVec.at(plane);
392  longPulseWidth = (endT - startT) / nHitsThisPulse;
393  }
394 
395  if (nHitsThisPulse * longPulseWidth < endT - startT) nHitsThisPulse++;
396 
397  int firstTick = startT;
398  int lastTick = std::min(firstTick + longPulseWidth, endT);
399 
400  peakParamsVec.clear();
401  nGausForFit = nHitsThisPulse;
402  NDF = 1.;
403  chi2PerNDF = chi2PerNDF > fChi2NDF ? chi2PerNDF : -1.;
404 
405  for (int hitIdx = 0; hitIdx < nHitsThisPulse; hitIdx++) {
406  // This hit parameters
407  double ROIsumADC =
408  std::accumulate(range.begin() + firstTick, range.begin() + lastTick, 0.);
409  double peakSigma = (lastTick - firstTick) / 3.; // Set the width...
410  double peakAmp = 0.3989 * ROIsumADC / peakSigma; // Use gaussian formulation
411  double peakMean = (firstTick + lastTick) / 2.;
412 
413  // Store hit params
415 
416  peakParams.peakCenter = peakMean;
417  peakParams.peakCenterError = 0.1 * peakMean;
418  peakParams.peakSigma = peakSigma;
419  peakParams.peakSigmaError = 0.1 * peakSigma;
420  peakParams.peakAmplitude = peakAmp;
421  peakParams.peakAmplitudeError = 0.1 * peakAmp;
422 
423  peakParamsVec.push_back(peakParams);
424 
425  // set for next loop
426  firstTick = lastTick;
427  lastTick = std::min(lastTick + longPulseWidth, endT);
428  }
429  }
430 
431  // #######################################################
432  // ### Loop through returned peaks and make recob hits ###
433  // #######################################################
434 
435  int numHits(0);
436 
437  // Make a container for what will be the filtered collection
438  std::vector<recob::Hit> filteredHitVec;
439 
440  float nextpeak(0);
441  float prevpeak(0);
442  float nextpeakSig(0);
443  float prevpeakSig(0);
444  float nsigmaADC(2.0);
445  float newright(0);
446  float newleft(0);
447  for (const auto& peakParams : peakParamsVec) {
448  // Extract values for this hit
449  float peakAmp = peakParams.peakAmplitude;
450  float peakMean = peakParams.peakCenter;
451  float peakWidth = peakParams.peakSigma;
452 
453  //std::cout<<" ans hits "<<numHits<<" gaus "<<nGausForFit<<std::endl;
454 
455  //ANS get prev and next
456  if (numHits == 0) {
457  newleft = -9999;
458  newright = 9999;
459  nextpeak = 0;
460  prevpeak = 0;
461  nextpeakSig = 0;
462  prevpeakSig = 0;
463  }
464  if (numHits < nGausForFit - 1) {
465  nextpeak = (peakParamsVec.at(numHits + 1)).peakCenter;
466  nextpeakSig = (peakParamsVec.at(numHits + 1)).peakSigma;
467  //std::cout<<" ans size "<<peakParamsVec.size()<<" hit "<<numHits<<" next peak "<<nextpeak<<" sig "<<nextpeakSig<<std::endl;
468  }
469  if (numHits > 0) {
470  prevpeak = (peakParamsVec.at(numHits - 1)).peakCenter;
471  prevpeakSig = (peakParamsVec.at(numHits - 1)).peakSigma;
472  //std::cout<<" ans size "<<peakParamsVec.size()<<"hit "<<numHits<<" prev peak "<<prevpeak<<" sig "<<prevpeakSig<<std::endl;
473  }
474 
475  // Place one bit of protection here
476  if (std::isnan(peakAmp)) {
477  std::cout << "**** hit peak amplitude is a nan! Channel: " << channel
478  << ", start tick: " << startT << std::endl;
479  continue;
480  }
481 
482  // Extract errors
483  float peakAmpErr = peakParams.peakAmplitudeError;
484  float peakMeanErr = peakParams.peakCenterError;
485  float peakWidthErr = peakParams.peakSigmaError;
486 
487  // ### Charge ###
488  float charge =
489  chargeFunc(peakMean, peakAmp, peakWidth, fAreaNormsVec[plane], startT, endT);
490  ;
491  float chargeErr =
492  std::sqrt(TMath::Pi()) * (peakAmpErr * peakWidthErr + peakWidthErr * peakAmpErr);
493 
494  // ### limits for getting sums
495  std::vector<float>::const_iterator sumStartItr = range.begin() + startT;
496  std::vector<float>::const_iterator sumEndItr = range.begin() + endT;
497 
498  //### limits for the sum of the Hit based on the gaussian peak and sigma
499  std::vector<float>::const_iterator HitsumStartItr =
500  range.begin() + peakMean - nsigmaADC * peakWidth;
502  range.begin() + peakMean + nsigmaADC * peakWidth;
503 
504  if (nGausForFit > 1) {
505  if (numHits > 0) {
506  if ((peakMean - nsigmaADC * peakWidth) < (prevpeak + nsigmaADC * prevpeakSig)) {
507  float difPeak = peakMean - prevpeak;
508  float weightpeak = prevpeakSig / (prevpeakSig + peakWidth);
509  HitsumStartItr = range.begin() + prevpeak + difPeak * weightpeak;
510  newleft = prevpeak + difPeak * weightpeak;
511  }
512  }
513 
514  if (numHits < nGausForFit - 1) {
515  if ((peakMean + nsigmaADC * peakWidth) > (nextpeak - nsigmaADC * nextpeakSig)) {
516  float difPeak = nextpeak - peakMean;
517  float weightpeak = peakWidth / (nextpeakSig + peakWidth);
518  HitsumEndItr = range.begin() + peakMean + difPeak * weightpeak;
519  newright = peakMean + difPeak * weightpeak;
520  }
521  }
522  }
523 
524  //protection to avoid negative ranges
525  if (newright - newleft < 0) continue;
526  if (HitsumStartItr > HitsumEndItr) continue;
527 
528  //avoid ranges out of ROI if it happens
529  if (HitsumStartItr < sumStartItr) HitsumStartItr = sumStartItr;
530 
531  if (HitsumEndItr > sumEndItr) HitsumEndItr = sumEndItr;
532 
533  // ### Sum of ADC counts
534  double ROIsumADC = std::accumulate(sumStartItr, sumEndItr, 0.);
535  double HitsumADC = std::accumulate(HitsumStartItr, HitsumEndItr, 0.);
536 
537  // ok, now create the hit
538  recob::HitCreator hitcreator(
539  *wire, // wire reference
540  wid, // wire ID
541  startT + roiFirstBinTick, // start_tick TODO check
542  endT + roiFirstBinTick, // end_tick TODO check
543  peakWidth, // rms
544  peakMean + roiFirstBinTick, // peak_time
545  peakMeanErr, // sigma_peak_time
546  peakAmp, // peak_amplitude
547  peakAmpErr, // sigma_peak_amplitude
548  charge, // hit_integral
549  chargeErr, // hit_sigma_integral
550  ROIsumADC, // summedADC of the ROI
551  HitsumADC, // summedADC of the Hit
552  nGausForFit, // multiplicity
553  numHits, // local_index TODO check that the order is correct
554  chi2PerNDF, // goodness_of_fit
555  NDF // dof
556  );
557 
558  if (filteredHitCol) filteredHitVec.push_back(hitcreator.copy());
559 
560  const recob::Hit hit(hitcreator.move());
561 
562  // This loop will store ALL hits
563  hitstruct tmp{std::move(hit), wire};
564  hitstruct_vec.push_back(std::move(tmp));
565 
566  numHits++;
567  } // <---End loop over gaussians
568 
569  // Should we filter hits?
570  if (filteredHitCol && !filteredHitVec.empty()) {
571  // #######################################################################
572  // Is all this sorting really necessary? Would it be faster to just loop
573  // through the hits and perform simple cuts on amplitude and width on a
574  // hit-by-hit basis, either here in the module (using fPulseHeightCuts and
575  // fPulseWidthCuts) or in HitFilterAlg?
576  // #######################################################################
577 
578  // Sort in ascending peak height
579  std::sort(filteredHitVec.begin(),
580  filteredHitVec.end(),
581  [](const auto& left, const auto& right) {
582  return left.PeakAmplitude() > right.PeakAmplitude();
583  });
584 
585  // Reject if the first hit fails the PH/wid cuts
586  if (filteredHitVec.front().PeakAmplitude() < fPulseHeightCuts.at(plane) ||
587  filteredHitVec.front().RMS() < fPulseWidthCuts.at(plane))
588  filteredHitVec.clear();
589 
590  // Now check other hits in the snippet
591  if (filteredHitVec.size() > 1) {
592  // The largest pulse height will now be at the front...
593  float largestPH = filteredHitVec.front().PeakAmplitude();
594 
595  // Find where the pulse heights drop below threshold
596  float threshold(fPulseRatioCuts.at(plane));
597 
599  std::find_if(filteredHitVec.begin(),
600  filteredHitVec.end(),
601  [largestPH, threshold](const auto& hit) {
602  return hit.PeakAmplitude() < 8. &&
603  hit.PeakAmplitude() / largestPH < threshold;
604  });
605 
606  // Shrink to fit
607  if (smallHitItr != filteredHitVec.end())
608  filteredHitVec.resize(std::distance(filteredHitVec.begin(), smallHitItr));
609 
610  // Resort in time order
611  std::sort(filteredHitVec.begin(),
612  filteredHitVec.end(),
613  [](const auto& left, const auto& right) {
614  return left.PeakTime() < right.PeakTime();
615  });
616  }
617 
618  // Copy the hits we want to keep to the filtered hit collection
619  for (const auto& filteredHit : filteredHitVec)
620  if (!fHitFilterAlg || fHitFilterAlg->IsGoodHit(filteredHit)) {
621  hitstruct tmp{std::move(filteredHit), wire};
622  filthitstruct_vec.push_back(std::move(tmp));
623  }
624 
625  if (fFillHists) fChi2->Fill(chi2PerNDF);
626  }
627  } //<---End loop over merged candidate hits
628  } //<---End looping over ROI's
629  ); //end tbb parallel for
630  } //<---End looping over all the wires
631  ); //end tbb parallel for
632 
633  for (size_t i = 0; i < hitstruct_vec.size(); i++) {
634  allHitCol.emplace_back(hitstruct_vec[i].hit_tbb, hitstruct_vec[i].wire_tbb);
635  }
636 
637  for (size_t j = 0; j < filthitstruct_vec.size(); j++) {
638  filteredHitCol->emplace_back(filthitstruct_vec[j].hit_tbb, filthitstruct_vec[j].wire_tbb);
639  }
640 
641  //==================================================================================================
642  // End of the event -- move the hit collection and the associations into the event
643 
644  if (filteredHitCol) {
645 
646  // If we filtered hits but no instance name was
647  // specified for the "all hits" collection, then
648  // only save the filtered hits to the event
649  if (fAllHitsInstanceName == "") {
650  filteredHitCol->put_into(evt);
651 
652  // otherwise, save both
653  }
654  else {
655  filteredHitCol->put_into(evt);
656  allHitCol.put_into(evt);
657  }
658  }
659  else {
660  allHitCol.put_into(evt);
661  }
662  } // End of produce()
663 
665 
666 } // end of hit namespace
intermediate_table::iterator iterator
const datarange_t & range(size_t i) const
Returns the i-th non-void range (zero-based)
size_type n_ranges() const
Returns the internal list of non-void ranges.
constexpr auto const & right(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:102
recob::Hit const & copy() const
Returns the constructed wire.
Definition: HitCreator.h:355
std::unique_ptr< HitFilterAlg > fHitFilterAlg
algorithm used to filter out noise hits
Declaration of signal hit object.
void produce(art::Event &evt, art::ProcessingFrame const &) override
GausHitFinder(fhicl::ParameterSet const &pset, art::ProcessingFrame const &)
unsigned int PlaneID_t
Type for the ID number.
Definition: geo_types.h:365
cout<< "Opened file "<< fin<< " ixs= "<< ixs<< endl;if(ixs==0) hhh=(TH1F *) fff-> Get("h1")
Definition: AddMC.C:8
intermediate_table::const_iterator const_iterator
Float_t tmp
Definition: plot.C:35
const std::vector< int > fLongPulseWidthVec
Sets width of hits used to describe long pulses.
static void declare_products(art::ProducesCollector &collector, std::string instance_name="", bool doWireAssns=true, bool doRawDigitAssns=true)
Declares the hit products we are going to fill.
Definition: HitCreator.cxx:261
std::unique_ptr< reco_tool::IPeakFitter > fPeakFitterTool
Perform fit to candidate peaks.
const int fAreaMethod
Type of area calculation.
const std::string fCalDataModuleLabel
const std::vector< float > fPulseWidthCuts
int TDCtick_t
Type representing a TDC tick.
Definition: RawTypes.h:25
Class managing the creation of a new recob::Hit object.
Definition: HitCreator.h:87
std::vector< std::string > get_pset_names() const
Helper functions to create a hit.
A class handling a collection of hits and its associations.
Definition: HitCreator.h:489
#define DEFINE_ART_MODULE(klass)
Definition: ModuleMacros.h:65
raw::ChannelID_t Channel() const
Returns the ID of the channel (or InvalidChannelID)
Definition: Wire.h:223
SharedProducer(fhicl::ParameterSet const &pset)
std::vector< double > FillOutHitParameterVector(const std::vector< double > &input)
std::atomic< size_t > fEventCount
T get(std::string const &key) const
Definition: ParameterSet.h:314
const size_t fMaxMultiHit
maximum hits for multi fit
const std::vector< int > fLongMaxHitsVec
Maximum number hits on a really long pulse train.
const RegionsOfInterest_t & SignalROI() const
Returns the list of regions of interest.
Definition: Wire.h:211
void beginJob(art::ProcessingFrame const &) override
void emplace_back(recob::Hit &&hit, art::Ptr< recob::Wire > const &wire=art::Ptr< recob::Wire >(), art::Ptr< raw::RawDigit > const &digits=art::Ptr< raw::RawDigit >())
Adds the specified hit to the data collection.
Definition: HitCreator.cxx:299
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:373
void put_into(art::Event &)
Moves the data into an event.
Definition: HitCreator.h:622
Detector simulation of raw signals on wires.
ProducesCollector & producesCollector() noexcept
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
std::vector< PeakFitParams_t > PeakParamsVec
Definition: IPeakFitter.h:34
constexpr auto const & left(const_AssnsIter< L, R, D, Dir > const &a, const_AssnsIter< L, R, D, Dir > const &b)
Definition: AssnsIter.h:94
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
This provides an interface for tools which are tasked with fitting peaks on input waveforms...
const std::vector< float > fPulseRatioCuts
This provides an interface for tools which are tasked with finding candidate hits on input waveforms...
const std::vector< float > fPulseHeightCuts
maximum Chisquared / NDF allowed for a hit to be saved
Declaration of basic channel signal object.
const std::string fAllHitsInstanceName
2D representation of charge deposited in the TDC/wire plane
Definition: Hit.h:46
const std::vector< double > fAreaNormsVec
factors for converting area to same units as peak height
static Globals * instance()
Definition: Globals.cc:17
TCEvent evt
Definition: DataStructs.cxx:8
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
std::vector< HitCandidateVec > MergeHitCandidateVec
recob::Hit && move()
Prepares the constructed hit to be moved away.
Definition: HitCreator.h:338
Definition: fwd.h:26
std::vector< std::unique_ptr< reco_tool::ICandidateHitFinder > > fHitFinderToolVec
For finding candidate hits.
std::vector< HitCandidate > HitCandidateVec