All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ROIFinderStandardSBND_tool.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file ROIFinderStandardSBND_tool.cc
3 /// \author T. Usher
4 /// Ported from ICARUS to SBND by A. Scarff
5 ////////////////////////////////////////////////////////////////////////
6 #include <cmath>
8 #include "art/Utilities/ToolMacros.h"
9 #include "art_root_io/TFileService.h"
10 #include "messagefacility/MessageLogger/MessageLogger.h"
11 #include "cetlib_except/exception.h"
15 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
16 #include "TH1D.h"
17 #include <fstream>
18 #include <algorithm>
19 #include <numeric> // std::accumulate
20 
21 namespace sbnd_tool
22 {
24  {
25  public:
26  explicit ROIFinderStandardSBND(const fhicl::ParameterSet& pset);
27 
29 
30  void configure(const fhicl::ParameterSet& pset) override;
31  void initializeHistograms(art::TFileDirectory&) const override;
32  size_t plane() const override {return fPlane;}
33  void FindROIs(const Waveform&, size_t, CandidateROIVec&) const override;
34  double calculateLocalRMS(const Waveform& waveform) const;
35  private:
36  // Member variables from the fhicl file
37  size_t fPlane;
38  float fNumBinsHalf; ///< Determines # bins in ROI running sum
39  std::vector<float> fThreshold; ///< abs(threshold) ADC counts for ROI
40  std::vector<int> fNumSigma; ///< "# sigma" rms noise for ROI threshold
41  std::vector<float> fPreROIPad; ///< ROI padding
42  std::vector<float> fPostROIPad; ///< ROI padding
43 
44  // Services
45  const geo::GeometryCore* fGeometry = lar::providerFrom<geo::Geometry>();
46  art::ServiceHandle<util::SignalShapingServiceSBND> sss;
47  };
48 
49  //----------------------------------------------------------------------
50  // Constructor.
51  ROIFinderStandardSBND::ROIFinderStandardSBND(const fhicl::ParameterSet& pset)
52  {
53  configure(pset);
54  }
55 
57  {
58  }
59 
60  void ROIFinderStandardSBND::configure(const fhicl::ParameterSet& pset)
61  {
62  // Start by recovering the parameters
63  std::vector<float> uin;
64  std::vector<float> vin;
65  std::vector<float> zin;
66 
67  fNumBinsHalf = pset.get<float> ("NumBinsHalf", 3);
68  fThreshold = pset.get< std::vector<float> >("Threshold" );
69  fNumSigma = pset.get< std::vector<int> > ("NumSigma" );
70  uin = pset.get< std::vector<float> >("uPlaneROIPad" );
71  vin = pset.get< std::vector<float> >("vPlaneROIPad" );
72  zin = pset.get< std::vector<float> >("zPlaneROIPad" );
73 
74  if(uin.size() != 2 || vin.size() != 2 || zin.size() != 2) {
75  throw art::Exception(art::errors::Configuration)
76  << "u/v/z plane ROI pad size != 2";
77  }
78 
79  fPreROIPad.resize(3);
80  fPostROIPad.resize(3);
81 
82  // put the ROI pad sizes into more convenient vectors
83  fPreROIPad[0] = uin[0];
84  fPostROIPad[0] = uin[1];
85  fPreROIPad[1] = vin[0];
86  fPostROIPad[1] = vin[1];
87  fPreROIPad[2] = zin[0];
88  fPostROIPad[2] = zin[1];
89 
90  // Get signal shaping service.
91  sss = art::ServiceHandle<util::SignalShapingServiceSBND>();
92 
93  return;
94  }
95 
96  //void ROIFinderStandardSBND::FindROIs(const Waveform& waveform, size_t channel, size_t cnt, double rmsNoise, CandidateROIVec& roiVec) const
97  void ROIFinderStandardSBND::FindROIs(const Waveform& waveform, size_t channel, CandidateROIVec& roiVec) const
98  {
99  // First up, translate the channel to plane
100  std::vector<geo::WireID> wids = fGeometry->ChannelToWire(channel);
101  const geo::PlaneID& planeID = wids[0].planeID();
102 
103  size_t numBins(2 * fNumBinsHalf + 1);
104  size_t startBin(0);
105  size_t stopBin(numBins);
106  float elecNoise = sss->GetRawNoise(channel);
107 
108  double rmsNoise = this->calculateLocalRMS(waveform); // added from ICARUS calculation.
109 
110  float rawNoise = std::max(rmsNoise, double(elecNoise));
111 
112  float startThreshold = sqrt(float(numBins)) * (fNumSigma[planeID.Plane] * rawNoise + fThreshold[planeID.Plane]);
113  float stopThreshold = startThreshold;
114 
115  // Setup
116  float runningSum = std::accumulate(waveform.begin(),waveform.begin()+numBins, 0.);
117 
118  size_t roiStartBin(0);
119  bool roiCandStart(false);
120 
121  // search for ROIs - follow prescription from Bruce B using a running sum to make faster
122  // Note that we start in the middle of the running sum... if we find an ROI padding will extend
123  // past this to take care of ends of the waveform
124  for(size_t bin = fNumBinsHalf + 1; bin < waveform.size() - fNumBinsHalf; bin++)
125  {
126  // handle the running sum
127  // Case, we are at start of waveform
128  runningSum -= waveform[startBin++];
129 
130  // Case, we are at end of waveform
131  runningSum += waveform[stopBin++];
132 
133  // We have already started a candidate ROI
134  if (roiCandStart)
135  {
136  if (fabs(runningSum) < stopThreshold)
137  {
138  if (bin - roiStartBin > 2) roiVec.push_back(CandidateROI(roiStartBin, bin));
139 
140  roiCandStart = false;
141  }
142  }
143  // Not yet started a candidate ROI
144  else
145  {
146  if (fabs(runningSum) > startThreshold)
147  {
148  roiStartBin = bin;
149  roiCandStart = true;
150  }
151  }
152  } // bin
153 
154  // add the last ROI if existed
155  if (roiCandStart) roiVec.push_back(CandidateROI(roiStartBin, waveform.size() - 1));
156 
157  // pad the ROIs
158  for(auto& roi : roiVec)
159  {
160  // low ROI end
161  roi.first = std::max(int(roi.first - fPreROIPad[planeID.Plane]),0);
162  // high ROI end
163  roi.second = std::min(roi.second + fPostROIPad[planeID.Plane], float(waveform.size()) - 1);
164  }
165 
166  // merge overlapping (or touching) ROI's
167  if(roiVec.size() > 1)
168  {
169  // temporary vector for merged ROIs
170  CandidateROIVec tempRoiVec;
171 
172  // Loop through candidate roi's
173  size_t startRoi = roiVec.front().first;
174  size_t stopRoi = startRoi;
175 
176  for(auto& roi : roiVec)
177  {
178  if (roi.first <= stopRoi) stopRoi = roi.second;
179  else
180  {
181  tempRoiVec.push_back(CandidateROI(startRoi,stopRoi));
182 
183  startRoi = roi.first;
184  stopRoi = roi.second;
185  }
186  }
187 
188  // Make sure to get the last one
189  tempRoiVec.push_back(CandidateROI(startRoi,stopRoi));
190 
191  roiVec = tempRoiVec;
192  }
193 
194  return;
195  }
196 
197 
199  {
200  // do rms calculation - the old fashioned way and over all adc values
201  std::vector<float> locWaveform = waveform;
202 
203  // sort in ascending order so we can truncate the sume
204  std::sort(locWaveform.begin(), locWaveform.end(),[](const auto& left, const auto& right){return std::fabs(left) < std::fabs(right);});
205 
206  // Get the mean of the waveform we're checking...
207  float sumWaveform = std::accumulate(locWaveform.begin(),locWaveform.begin() + locWaveform.size()/2, 0.);
208  float meanWaveform = sumWaveform / float(locWaveform.size()/2);
209 
210  std::vector<float> locWaveformDiff(locWaveform.size()/2);
211  std::transform(locWaveform.begin(),locWaveform.begin() + locWaveform.size()/2,locWaveformDiff.begin(), std::bind(std::minus<float>(),std::placeholders::_1,meanWaveform));
212 
213  double localRMS = std::inner_product(locWaveformDiff.begin(), locWaveformDiff.end(), locWaveformDiff.begin(), 0.);
214 
215  localRMS = std::sqrt(std::max(float(0.),float(localRMS) / float(locWaveformDiff.size())));
216 
217  return(localRMS);
218 
219  }
220 
221  void ROIFinderStandardSBND::initializeHistograms(art::TFileDirectory& histDir) const
222  {
223  // It is assumed that the input TFileDirectory has been set up to group histograms into a common
224  // folder at the calling routine's level. Here we create one more level of indirection to keep
225  // histograms made by this tool separate.
226  /*
227  std::string dirName = "ROIFinderPlane_" + std::to_string(fPlane);
228 
229  art::TFileDirectory dir = histDir.mkdir(dirName.c_str());
230 
231  auto const* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
232  double samplingRate = detprop->SamplingRate();
233  double numBins = fROIFinderVec.size();
234  double maxFreq = 500. / samplingRate;
235  std::string histName = "ROIFinderPlane_" + std::to_string(fPlane);
236 
237  TH1D* hist = dir.make<TH1D>(histName.c_str(), "ROIFinder;Frequency(MHz)", numBins, 0., maxFreq);
238 
239  for(int bin = 0; bin < numBins; bin++)
240  {
241  double freq = maxFreq * double(bin + 0.5) / double(numBins);
242 
243  hist->Fill(freq, fROIFinderVec.at(bin).Re());
244  }
245  */
246 
247  return;
248  }
249 
250  DEFINE_ART_CLASS_TOOL(ROIFinderStandardSBND)
251 }
Utilities related to art service access.
void FindROIs(const Waveform &, size_t, CandidateROIVec &) const override
static constexpr Sample_t transform(Sample_t sample)
std::vector< int > fNumSigma
&quot;# sigma&quot; rms noise for ROI threshold
float fNumBinsHalf
Determines # bins in ROI running sum.
walls no right
Definition: selectors.fcl:105
The data type to uniquely identify a Plane.
Definition: geo_types.h:472
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
std::vector< float > fThreshold
abs(threshold) ADC counts for ROI
std::vector< float > fPostROIPad
ROI padding.
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
Service to provide microboone-specific signal shaping for simulation (convolution) and reconstruction...
double calculateLocalRMS(const Waveform &waveform) const
walls no left
Definition: selectors.fcl:105
PlaneID_t Plane
Index of the plane within its TPC.
Definition: geo_types.h:493
Description of geometry of one entire detector.
void initializeHistograms(art::TFileDirectory &) const override
art::ServiceHandle< util::SignalShapingServiceSBND > sss
void configure(const fhicl::ParameterSet &pset) override
ROIFinderStandardSBND(const fhicl::ParameterSet &pset)
art framework interface to geometry description
std::vector< float > fPreROIPad
ROI padding.