All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
OpHitFinder_tool.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file OpHitFinder.cc
3 /// \author T. Usher
4 ////////////////////////////////////////////////////////////////////////
5 
6 #include "art/Utilities/ToolMacros.h"
7 #include "art/Utilities/make_tool.h"
8 #include "art/Framework/Principal/Handle.h"
9 #include "art_root_io/TFileService.h"
10 #include "messagefacility/MessageLogger/MessageLogger.h"
11 #include "cetlib_except/exception.h"
12 
15 
16 #include <cmath>
17 #include <fstream>
18 
19 namespace light
20 {
21 
22 class OpHitFinder : public IOpHitFinder
23 {
24 public:
25  explicit OpHitFinder(const fhicl::ParameterSet& pset);
26 
27  ~OpHitFinder();
28 
29  void configure(const fhicl::ParameterSet& pset) override;
30  void outputHistograms(art::TFileDirectory&) const override;
31 
32  void FindOpHits(const raw::OpDetWaveform&, OpHitVec&) const override;
33 
34 private:
35  // fhicl parameters
36  float fSPEArea; //< conversion between phe and Adc*ns
37  float fSaturationCut; //< Saturation occurs at this point
38  int fMaxSatChannels; //< maximum saturated channels
39  mutable size_t fEventCount; //< Keep track of the number of events processed
40 
41  float getBaseline(const raw::OpDetWaveform&) const;
42 
43  std::unique_ptr<reco_tool::ICandidateHitFinder> fHitFinderTool; ///< For finding candidate hits
44 };
45 
46 //----------------------------------------------------------------------
47 // Constructor.
48 OpHitFinder::OpHitFinder(const fhicl::ParameterSet& pset)
49 {
50  configure(pset);
51 }
52 
54 {
55 }
56 
57 void OpHitFinder::configure(const fhicl::ParameterSet& pset)
58 {
59  // Start by recovering the parameters
60  fSPEArea = pset.get< float >("SPEArea" );
61  fSaturationCut = pset.get< float >("SaturationCut", 3000.);
62  fMaxSatChannels = pset.get< int >("MaxSatChannels", 10);
63 
64  fEventCount = 0;
65 
66  fHitFinderTool = art::make_tool<reco_tool::ICandidateHitFinder>(pset.get<fhicl::ParameterSet>("CandidateHits"));
67 
68  return;
69 }
70 
71 
72 void OpHitFinder::FindOpHits(const raw::OpDetWaveform& opDetWaveform,
73  OpHitVec& opHitVec) const
74 {
75  // The plan here:
76  // 1) Get the baseline
77  // 2) Copy to a local vector doing baseline subtraction and inversion
78  // 3) Set up and call the standard gaushit finder tools for finding peaks
79  // 4) Return the parameters for an ophit
80  float baseline = getBaseline(opDetWaveform);
81 
82  std::vector<float> locWaveform;
83 
84  locWaveform.resize(opDetWaveform.size());
85 
86  // The aim here is to baseline correct AND invert the waveform
87  std::transform(opDetWaveform.begin(),opDetWaveform.end(),locWaveform.begin(),[baseline](const auto& val){return baseline - val;});
88 
89  std::pair<std::vector<float>::iterator,std::vector<float>::iterator> minMaxItr = std::minmax_element(locWaveform.begin(),locWaveform.end());
90 
93 
94  bool notSaturated(true);
95  int numSatChans(0);
96  float maxAdc = *minMaxItr.second;
97  float minAdc = *minMaxItr.first;
98 
99  if (maxAdc - minAdc > fSaturationCut)
100  {
101  float unSatAdc = 0.5 * (maxAdc - minAdc) + minAdc;
102  std::vector<float>::iterator unSatItr = std::find_if(minMaxItr.second,locWaveform.end(),[unSatAdc](const auto& elem){return elem < unSatAdc;});
103 
104  numSatChans = std::distance(minMaxItr.second,unSatItr);
105 
106  if (numSatChans > fMaxSatChannels) notSaturated = false;
107  }
108 
109  if (notSaturated)
110  {
111  std::vector<float> tempVec = locWaveform;
112  recob::Wire::RegionsOfInterest_t::datarange_t rangeData(size_t(0),std::move(tempVec));
113 
114  fHitFinderTool->findHitCandidates(rangeData, 0, 0, fEventCount, hitCandidateVec);
115  fHitFinderTool->MergeHitCandidates(rangeData, hitCandidateVec, mergedCandidateHitVec);
116  }
117  else
118  {
120 
121  hitCandidate.startTick = 0;
122  hitCandidate.stopTick = 0;
123  hitCandidate.maxTick = 0;
124  hitCandidate.minTick = 0;
125  hitCandidate.maxDerivative = 0;
126  hitCandidate.minDerivative = 0;
127  hitCandidate.hitCenter = std::distance(locWaveform.begin(),minMaxItr.second);
128  hitCandidate.hitSigma = std::min(40,numSatChans);
129  hitCandidate.hitHeight = maxAdc - minAdc;
130 
131  std::cout << "***>> Saturated PMT, numSatChans: " << numSatChans << ", range: " << maxAdc-minAdc << std::endl;
132 
133  hitCandidateVec.push_back(hitCandidate);
134  mergedCandidateHitVec.push_back(hitCandidateVec);
135  }
136 
137  // Recover the channel number
138  raw::Channel_t chNumber = opDetWaveform.ChannelNumber();
139 
140  // Go through the hit candidates and convert to ophits
141  // Note that the "merged candidates" represent lists of candidate hits that
142  // are in one pulse train... so we need a double loop
143  for(const auto& mergedCands : mergedCandidateHitVec)
144  {
145  for(const auto& candidateHit : mergedCands)
146  {
147  float peakMean = candidateHit.hitCenter;
148  float peakSigma = candidateHit.hitSigma;
149  float amplitude = candidateHit.hitHeight;
150  float peakArea = amplitude * peakSigma * 2.5066; // * sqrt(2pi)
151  float nPhotoElec = peakArea / fSPEArea;
152 
153  float peakTimeAbs = peakMean; // NOTE: these times will need to be corrected
154  int frame = 1; // also this needs to be the clock frame
155  float fastTotal = 0.; // not sure what this is
156 
157  opHitVec.emplace_back(chNumber, peakMean, peakTimeAbs, frame, 2.35 * peakSigma, peakArea, amplitude, nPhotoElec, fastTotal);//including hit info
158  }
159  }
160 
161  fEventCount++;
162 
163  return;
164 }
165 
166 float OpHitFinder::getBaseline(const raw::OpDetWaveform& locWaveform) const
167 {
168  // Fill a map to determine the most probable value
169  std::map<raw::ADC_Count_t,int> adcFrequencyMap;
170 
171  raw::ADC_Count_t maxBin(0);
172  int maxCount(0);
173 
174  for(const auto& adc : locWaveform)
175  {
176  int& adcFrequency = adcFrequencyMap[adc];
177 
178  if (++adcFrequency > maxCount)
179  {
180  maxBin = adc;
181  maxCount = adcFrequency;
182  }
183  }
184 
185  float mostProbableBaseline(0.);
186  int mostProbableCount(0);
187 
188  for(raw::ADC_Count_t adcBin = maxBin - 3; adcBin <= maxBin + 3; adcBin++)
189  {
190  try{
191  mostProbableBaseline += adcFrequencyMap.at(adcBin) * float(adcBin);
192  mostProbableCount += adcFrequencyMap.at(adcBin);
193  }
194  catch(...) {}
195  }
196 
197  mostProbableBaseline /= mostProbableCount;
198 
199  return mostProbableBaseline;
200 }
201 
202 
203 void OpHitFinder::outputHistograms(art::TFileDirectory& histDir) const
204 {
205  // It is assumed that the input TFileDirectory has been set up to group histograms into a common
206  // folder at the calling routine's level. Here we create one more level of indirection to keep
207  // histograms made by this tool separate.
208 /*
209  std::string dirName = "OpHitFinderPlane_" + std::to_string(fPlane);
210 
211  art::TFileDirectory dir = histDir.mkdir(dirName.c_str());
212 
213  auto const* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
214  double samplingRate = detprop->SamplingRate();
215  double numBins = fOpHitFinderVec.size();
216  double maxFreq = 500. / samplingRate;
217  std::string histName = "OpHitFinderPlane_" + std::to_string(fPlane);
218 
219  TH1D* hist = dir.make<TH1D>(histName.c_str(), "OpHitFinder;Frequency(MHz)", numBins, 0., maxFreq);
220 
221  for(int bin = 0; bin < numBins; bin++)
222  {
223  double freq = maxFreq * double(bin + 0.5) / double(numBins);
224 
225  hist->Fill(freq, fOpHitFinderVec.at(bin).Re());
226  }
227 */
228 
229  return;
230 }
231 
232 DEFINE_ART_CLASS_TOOL(OpHitFinder)
233 }
static constexpr Sample_t transform(Sample_t sample)
void configure(const fhicl::ParameterSet &pset) override
void FindOpHits(const raw::OpDetWaveform &, OpHitVec &) const override
float getBaseline(const raw::OpDetWaveform &) const
std::unique_ptr< reco_tool::ICandidateHitFinder > fHitFinderTool
For finding candidate hits.
OpHitFinder(const fhicl::ParameterSet &pset)
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
BEGIN_PROLOG baseline
This provides an interface for tools which are tasked with finding the baselines in input waveforms...
This provides an interface for tools which are tasked with finding candidate hits on input waveforms...
std::vector< HitCandidateVec > MergeHitCandidateVec
void outputHistograms(art::TFileDirectory &) const override
std::vector< recob::OpHit > OpHitVec
Definition: IOpHitFinder.h:26
BEGIN_PROLOG could also be cout
std::vector< HitCandidate > HitCandidateVec