All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
BasicRawDigitAnalysis_tool.cc
Go to the documentation of this file.
2 
3 #include "fhiclcpp/ParameterSet.h"
4 #include "art/Utilities/ToolMacros.h"
5 #include "art/Framework/Services/Registry/ServiceHandle.h"
6 #include "art_root_io/TFileService.h"
7 #include "art/Framework/Core/ModuleMacros.h"
8 #include "art/Utilities/make_tool.h"
9 #include "art_root_io/TFileDirectory.h"
10 #include "messagefacility/MessageLogger/MessageLogger.h"
11 
13 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
19 
22 
23 #include "TH1.h"
24 #include "TH2.h"
25 #include "TProfile.h"
26 #include "TProfile2D.h"
27 #include "TF1.h"
28 
29 #include "icarus_signal_processing/Filters/ICARUSFFT.h"
30 #include "icarus_signal_processing/WaveformTools.h"
31 
32 #include <cmath>
33 #include <algorithm>
34 #include <vector>
35 
37 {
38  ////////////////////////////////////////////////////////////////////////
39  //
40  // Class: BasicRawDigitAnalysis
41  // Module Type: producer
42  // File: BasicRawDigitAnalysis.h
43  //
44  // The intent of this module is to provide methods for
45  // "analyzing" hits on waveforms
46  //
47  // Configuration parameters:
48  //
49  // TruncMeanFraction - the fraction of waveform bins to discard when
50  //
51  // Created by Tracy Usher (usher@slac.stanford.edu) on February 19, 2016
52  //
53  ////////////////////////////////////////////////////////////////////////
54 
56 {
57 public:
58  /**
59  * @brief Constructor
60  *
61  * @param pset
62  */
63  explicit BasicRawDigitAnalysis(fhicl::ParameterSet const & pset);
64 
65  /**
66  * @brief Destructor
67  */
69 
70  // provide for initialization
71  void configure(fhicl::ParameterSet const & pset) override;
72 
73  /**
74  * @brief Interface for initializing the histograms to be filled
75  *
76  * @param TFileService handle to the TFile service
77  * @param string subdirectory to store the hists in
78  */
79  void initializeHists(detinfo::DetectorClocksData const& clockData,
81  art::ServiceHandle<art::TFileService>&, const std::string&) override;
82 
83  /**
84  * @brief Interface for method to executve at the end of run processing
85  *
86  * @param int number of events to use for normalization
87  */
88  void endJob(int numEvents) override;
89 
90  /**
91  * @brief Interface for filling histograms
92  */
93  void fillHistograms(const detinfo::DetectorClocksData& clockData,
94  const detinfo::DetectorPropertiesData& detProp,
96  const IRawDigitHistogramTool::SimChannelMap&) const override;
97 
98 private:
99  void filterFFT(const detinfo::DetectorClocksData& clockData,
100  const detinfo::DetectorPropertiesData& detProp,
101  std::vector<short>&, raw::ChannelID_t, size_t, size_t, float, bool) const;
102 
103  // Fcl parameters.
104  std::vector<size_t> fLoWireByPlane; ///< Low wire for individual wire histograms
105  std::vector<size_t> fHiWireByPlane; ///< Hi wire for individual wire histograms
106  std::vector<std::string> fFFTFitFuncVec; ///< Function definitions for fitting the average FFT power spectra
107  std::vector<std::vector<double>> fParameterVec; ///< Initial parameters for fit function
108 
109  // Pointers to the histograms we'll create.
110  std::vector<TH1D*> fTruncMeanHist;
111  std::vector<TH1D*> fTruncRmsHist;
112  std::vector<TH1D*> fFullRmsHist;
113 
114  std::vector<std::vector<TProfile*>> fFFTPowerVec;
115  std::vector<std::vector<TProfile*>> fFFTPowerDerivVec;
116  std::vector<std::vector<TProfile*>> fFFTRealVec;
117  std::vector<std::vector<TProfile*>> fFFTImaginaryVec;
118  std::vector<std::vector<TProfile*>> fSmoothPowerVec;
119 
120  std::vector<TProfile*> fAveFFTPowerVec;
121  std::vector<TProfile*> fConvFFTPowerVec;
122  std::vector<TProfile*> fConvKernelVec;
123  std::vector<TProfile*> fFilterFuncVec;
124  std::vector<TProfile*> fAveFFTPowerDerivVec;
125  std::vector<TProfile*> fAveFFTRealVec;
126  std::vector<TProfile*> fAveFFTImaginaryVec;
127  std::vector<TProfile*> fAveSmoothPowerVec;
128 
130 
131  using WaveformTools = icarus_signal_processing::WaveformTools<double>;
132 
134 
135  using FFTPointer = std::unique_ptr<icarus_signal_processing::ICARUSFFT<double>>;
136 
137  FFTPointer fFFT; //< Object to handle thread safe FFT
138 
139  // Useful services, keep copies for now (we can update during begin run periods)
140  const geo::GeometryCore& fGeometry; ///< pointer to Geometry service
141  icarusutil::SignalShapingICARUSService& fSignalServices; ///< The signal shaping service
142  const lariov::DetPedestalProvider& fPedestalRetrievalAlg; ///< Keep track of an instance to the pedestal retrieval alg
143 };
144 
145 //----------------------------------------------------------------------------
146 /// Constructor.
147 ///
148 /// Arguments:
149 ///
150 /// pset - Fcl parameters.
151 ///
152 BasicRawDigitAnalysis::BasicRawDigitAnalysis(fhicl::ParameterSet const & pset) :
153  fCharacterizationAlg(pset.get<fhicl::ParameterSet>("CharacterizationAlg")),
154  fGeometry(*lar::providerFrom<geo::Geometry>()),
155  fSignalServices(*art::ServiceHandle<icarusutil::SignalShapingICARUSService>()),
156  fPedestalRetrievalAlg(*lar::providerFrom<lariov::DetPedestalService>())
157 {
158  // Now set up our plans for doing the convolution
159  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataForJob();
160  int numberTimeSamples = detProp.NumberTimeSamples();
161 
162  fFFT = std::make_unique<icarus_signal_processing::ICARUSFFT<double>>(numberTimeSamples);
163 
164  configure(pset);
165 
166  // Report.
167  mf::LogInfo("BasicRawDigitAnalysis") << "BasicRawDigitAnalysis configured\n";
168 }
169 
170 //----------------------------------------------------------------------------
171 /// Destructor.
172 BasicRawDigitAnalysis::~BasicRawDigitAnalysis()
173 {}
174 
175 //----------------------------------------------------------------------------
176 /// Reconfigure method.
177 ///
178 /// Arguments:
179 ///
180 /// pset - Fcl parameter set.
181 ///
182 void BasicRawDigitAnalysis::configure(fhicl::ParameterSet const & pset)
183 {
184  fLoWireByPlane = pset.get<std::vector<size_t>> ("LoWireByPlane", std::vector<size_t>()={0,0,0});
185  fHiWireByPlane = pset.get<std::vector<size_t>> ("HiWireByPlane", std::vector<size_t>()={100,100,100});
186  fFFTFitFuncVec = pset.get<std::vector<std::string>> ("FFTFunctionVec", std::vector<std::string>()={"1","1","1"});
187  fParameterVec = pset.get<std::vector<std::vector<double>>>("FFTFuncParamsVec", std::vector<std::vector<double>>() = {{1},{1},{1}});
188 
189  //const fhicl::ParameterSet& waveformParamSet = pset.get<fhicl::ParameterSet>("WaveformTool");
190 }
191 
192 //----------------------------------------------------------------------------
193 /// Begin job method.
194 void BasicRawDigitAnalysis::initializeHists(detinfo::DetectorClocksData const& clockData,
196  art::ServiceHandle<art::TFileService>& tfs, const std::string& dirName)
197 {
198  // Make a directory for these histograms
199  art::TFileDirectory dir = tfs->mkdir(dirName.c_str());
200 
201  // Define the histograms. Putting semi-colons around the title
202  // causes it to be displayed as the x-axis label if the histogram
203  // is drawn.
204 
205  // hijack hists here
206  double sampleRate = sampling_rate(clockData);
207  double readOutSize = detProp.ReadOutWindowSize();
208  double maxFreq = 1.e6 / (2. * sampleRate);
209  size_t numSamples = readOutSize / 2;
210 
211  fTruncMeanHist.resize(3);
212  fTruncRmsHist.resize(3);
213  fFullRmsHist.resize(3);
214 
215  fFFTPowerVec.resize(3);
216  fFFTPowerDerivVec.resize(3);
217  fFFTRealVec.resize(3);
218  fFFTImaginaryVec.resize(3);
219  fSmoothPowerVec.resize(3);
220 
221  fAveFFTPowerVec.resize(3);
222  fConvFFTPowerVec.resize(3);
223  fConvKernelVec.resize(3);
224  fFilterFuncVec.resize(3);
225  fAveFFTPowerDerivVec.resize(3);
226  fAveFFTRealVec.resize(3);
227  fAveFFTImaginaryVec.resize(3);
228  fAveSmoothPowerVec.resize(3);
229 
230  for(size_t plane = 0; plane < fGeometry.Nplanes(); plane++)
231  {
232  size_t numHists = fHiWireByPlane[plane] - fLoWireByPlane[plane];
233 
234  fFFTPowerVec[plane].resize(numHists);
235  fFFTPowerDerivVec[plane].resize(numHists);
236  fFFTRealVec[plane].resize(numHists);
237  fFFTImaginaryVec[plane].resize(numHists);
238  fSmoothPowerVec[plane].resize(numHists);
239 
240  for(size_t idx = 0; idx < 20; idx++)
241  {
242  std::string histName = "FFTPower_" + std::to_string(plane) + "-" + std::to_string(idx);
243 
244  fFFTPowerVec[plane][idx] = dir.make<TProfile>(histName.c_str(), "Power Spectrum;kHz;Power", numSamples, 0., maxFreq, 0., 10000.);
245 
246  histName = "FFTPowerDeriv_" + std::to_string(plane) + "-" + std::to_string(idx);
247 
248  fFFTPowerDerivVec[plane][idx] = dir.make<TProfile>(histName.c_str(), "Power Deriv;kHz;Power", numSamples, 0., maxFreq, -500., 500.);
249 
250  histName = "FFTReal_" + std::to_string(plane) + "-" + std::to_string(idx);
251 
252  fFFTRealVec[plane][idx] = dir.make<TProfile>(histName.c_str(), "Real values;kHz;Power", numSamples, 0., maxFreq, -10000., 10000.);
253 
254  histName = "FFTImaginary_" + std::to_string(plane) + "-" + std::to_string(idx);
255 
256  fFFTImaginaryVec[plane][idx] = dir.make<TProfile>(histName.c_str(), "Imaginary values;kHz;Power", numSamples, 0., maxFreq, -10000., 10000.);
257 
258  histName = "SmoothPWR_" + std::to_string(plane) + "-" + std::to_string(idx);
259 
260  fSmoothPowerVec[plane][idx] = dir.make<TProfile>(histName.c_str(), "Power Spectrum;kHz;Power", numSamples, 0., maxFreq, 0., 10000.);
261  }
262 
263  std::string histName = "AveFFTPower_" + std::to_string(plane);
264 
265  fAveFFTPowerVec[plane] = dir.make<TProfile>(histName.c_str(), "Power Spectrum;kHz;Power", numSamples, 0., maxFreq, 0., 1000.);
266 
267  histName = "ConvFFTPower_" + std::to_string(plane);
268 
269  fConvFFTPowerVec[plane] = dir.make<TProfile>(histName.c_str(), "Power Spectrum;kHz;Power", numSamples, 0., maxFreq, 0., 1000.);
270 
271  histName = "ConvKernel_" + std::to_string(plane);
272 
273  fConvKernelVec[plane] = dir.make<TProfile>(histName.c_str(), "Convolution Kernel;kHz;Power", numSamples, 0., maxFreq, 0., 1000.);
274 
275  histName = "FilterFunc_" + std::to_string(plane);
276 
277  fFilterFuncVec[plane] = dir.make<TProfile>(histName.c_str(), "Filter Function;kHz;Power", numSamples, 0., maxFreq, 0., 1000.);
278 
279  histName = "AveFFTPowerDeriv_" + std::to_string(plane);
280 
281  fAveFFTPowerDerivVec[plane] = dir.make<TProfile>(histName.c_str(), "Power Deriv;kHz;Power", numSamples, 0., maxFreq, -500., 500.);
282 
283  histName = "AveFFTReal_" + std::to_string(plane);
284 
285  fAveFFTRealVec[plane] = dir.make<TProfile>(histName.c_str(), "Real values;kHz;Power", numSamples, 0., maxFreq, -10000., 1000.);
286 
287  histName = "AveFFTImaginary_" + std::to_string(plane);
288 
289  fAveFFTImaginaryVec[plane] = dir.make<TProfile>(histName.c_str(), "Imaginary values;kHz;Power", numSamples, 0., maxFreq, -1000., 1000.);
290 
291  histName = "AveSmoothPWR_" + std::to_string(plane);
292 
293  fAveSmoothPowerVec[plane] = dir.make<TProfile>(histName.c_str(), "Power Spectrum;kHz;Power", numSamples, 0., maxFreq, 0., 1000.);
294 
295  histName = "TruncMean_" + std::to_string(plane);
296 
297  fTruncMeanHist[plane] = dir.make<TH1D>(histName.c_str(), ";ADC", 200, -50., 50.);
298 
299  histName = "TruncRMS_" + std::to_string(plane);
300 
301  fTruncRmsHist[plane] = dir.make<TH1D>(histName.c_str(), ";ADC", 100, 0., 20.);
302 
303  histName = "FullRMS_" + std::to_string(plane);
304 
305  fFullRmsHist[plane] = dir.make<TH1D>(histName.c_str(), ";ADC", 100, 0., 20.);
306 
307  // Need a channel...
308  raw::ChannelID_t channel = fGeometry.PlaneWireToChannel(plane,0);
309 
310  // Recover the filter from signal shaping services...
313 
314  for(size_t idx = 0; idx < numSamples; idx++)
315  {
316  double freq = 1.e6 * double(idx)/ (sampleRate * readOutSize);
317  fConvKernelVec[plane]->Fill(freq, std::abs(response.at(idx)), 1.);
318  fFilterFuncVec[plane]->Fill(freq, std::abs(filter.at(idx)), 1.);
319  }
320  }
321 
322  return;
323 }
324 
325 void BasicRawDigitAnalysis::fillHistograms(const detinfo::DetectorClocksData& clockData,
327  const IRawDigitHistogramTool::RawDigitPtrVec& rawDigitPtrVec,
328  const IRawDigitHistogramTool::SimChannelMap& channelMap) const
329 {
330  // Sadly, the RawDigits come to us in an unsorted condition which is not optimal for
331  // what we want to do here. So we make a vector of pointers to the input raw digits and sort them
332  std::vector<const raw::RawDigit*> rawDigitVec;
333 
334  // Ugliness to fill the pointer vector...
335  for(size_t idx = 0; idx < rawDigitPtrVec.size(); idx++) rawDigitVec.push_back(rawDigitPtrVec.at(idx).get());
336 
337  // Sort (use a lambda to sort by channel id)
338  std::sort(rawDigitVec.begin(),rawDigitVec.end(),[](const raw::RawDigit* left, const raw::RawDigit* right) {return left->Channel() < right->Channel();});
339 
340  // Ok, to do the correlated noise removal we are going to need a rather impressive data structure...
341  // Because we need to unpack each wire's data, we will need to "explode" it out into a data structure
342  // here... with the good news that we'll release the memory at the end of the module so should not
343  // impact downstream processing (I hope!).
344  // What we are going to do is make a vector over planes of vectors over wires of vectors over time samples
345  //std::vector<RawDigitVector> rawDataWireTimeVec;
346  std::vector<caldata::RawDigitVector> rawDataWireTimeVec;
347  std::vector<float> truncMeanWireVec;
348  std::vector<float> truncRmsWireVec;
349  std::vector<short> meanWireVec;
350  std::vector<short> medianWireVec;
351  std::vector<short> modeWireVec;
352  std::vector<float> skewnessWireVec;
353  std::vector<float> fullRmsWireVec;
354  std::vector<short> minMaxWireVec;
355  std::vector<float> neighborRatioWireVec;
356  std::vector<float> pedCorWireVec;
357 
358  // We're stealing this from the raw digit filter, here we are going to set "number wires to group" to 1
359  size_t numWiresToGroup(1);
360 
361  rawDataWireTimeVec.resize(numWiresToGroup);
362  truncMeanWireVec.resize(numWiresToGroup);
363  truncRmsWireVec.resize(numWiresToGroup);
364  meanWireVec.resize(numWiresToGroup);
365  medianWireVec.resize(numWiresToGroup);
366  modeWireVec.resize(numWiresToGroup);
367  skewnessWireVec.resize(numWiresToGroup);
368  fullRmsWireVec.resize(numWiresToGroup);
369  minMaxWireVec.resize(numWiresToGroup);
370  neighborRatioWireVec.resize(numWiresToGroup);
371  pedCorWireVec.resize(numWiresToGroup);
372 
373  // Commence looping over raw digits
374  for(const auto& rawDigit : rawDigitVec)
375  {
376  raw::ChannelID_t channel = rawDigit->Channel();
377 
378  bool goodChan(true);
379 
380  // The below try-catch block may no longer be necessary
381  // Decode the channel and make sure we have a valid one
382  std::vector<geo::WireID> wids;
383  try {
384  wids = fGeometry.ChannelToWire(channel);
385  }
386  catch(...)
387  {
388  //std::cout << "===>> Found illegal channel with id: " << channel << std::endl;
389  goodChan = false;
390  }
391 
392  if (!goodChan) continue;
393 
394  // Recover plane and wire in the plane
395  unsigned int plane = wids[0].Plane;
396  unsigned int wire = wids[0].Wire;
397 
398  unsigned int dataSize = rawDigit->Samples();
399 
400  if (dataSize < 1)
401  {
402  std::cout << "****>> Found zero length raw digit buffer, channel: " << channel << ", plane: " << plane << ", wire: " << wire << std::endl;
403  continue;
404  }
405 
406  // If MC, does this channel have signal?
407  bool hasSignal = channelMap.find(channel) != channelMap.end();
408 
409  // vector holding uncompressed adc values
410  std::vector<short>& rawadc = rawDataWireTimeVec[0];
411 
412  if (rawadc.size() != dataSize) rawadc.resize(dataSize);
413 
414  // And now uncompress
415  raw::Uncompress(rawDigit->ADCs(), rawadc, rawDigit->Compression());
416 
417  // Recover the database version of the pedestal
418  float pedestal = fPedestalRetrievalAlg.PedMean(channel);
419 
420  filterFFT(clockData, detProp, rawadc, channel, plane, wire, pedestal, hasSignal);
421 
422  // Only rest if no signal on wire
423  if (!hasSignal)
424  {
425  // Get the kitchen sink
427  channel,
428  plane,
429  wire,
430  truncMeanWireVec[0],
431  truncRmsWireVec[0],
432  meanWireVec[0],
433  medianWireVec[0],
434  modeWireVec[0],
435  skewnessWireVec[0],
436  fullRmsWireVec[0],
437  minMaxWireVec[0],
438  neighborRatioWireVec[0],
439  pedCorWireVec[0]);
440 
441  // Now fill histograms...
442  fTruncMeanHist[plane]->Fill(truncMeanWireVec[0] - pedestal, 1.);
443  fTruncRmsHist[plane]->Fill(truncRmsWireVec[0], 1.);
444  fFullRmsHist[plane]->Fill(fullRmsWireVec[0], 1.);
445  }
446  }
447 
448  return;
449 }
450 
451 void BasicRawDigitAnalysis::filterFFT(detinfo::DetectorClocksData const& clockData,
453  std::vector<short>& rawadc,
454  raw::ChannelID_t channel,
455  size_t plane, size_t wire, float pedestal, bool hasSignal) const
456 {
457  double sampleRate = sampling_rate(clockData);
458  double readOutSize = detProp.ReadOutWindowSize();
459  // double binSize = sampleFreq / readOutSize;
460 
461  // Step one is to setup and then get the FFT transform of the input waveform
462  size_t fftDataSize = rawadc.size();
463  size_t halfFFTDataSize = fftDataSize / 2 + 1;
464 
465  icarusutil::TimeVec inputVec(fftDataSize, 0.);
466  icarusutil::TimeVec powerVec(fftDataSize, 0.);
467 
468  std::transform(rawadc.begin(),rawadc.end(),inputVec.begin(),[pedestal](const auto& val){return double(val) - pedestal;});
469 
470  fFFT->getFFTPower(inputVec,powerVec);
471 
472  // Fill any individual wire histograms we want to look at
473  if (wire >= fLoWireByPlane[plane] && wire < fHiWireByPlane[plane])
474  {
475  // Fill the power spectrum histogram
476  for(size_t idx = 0; idx < halfFFTDataSize; idx++)
477  {
478  double freq = 1.e6 * double(idx + 1)/ (sampleRate * readOutSize);
479  fFFTPowerVec[plane][wire-fLoWireByPlane[plane]]->Fill(freq, std::min(powerVec[idx],999.), 1.);
480  }
481  }
482 
483  for(size_t idx = 0; idx < halfFFTDataSize; idx++)
484  {
485  double freq = 1.e6 * double(idx + 1)/ (sampleRate * readOutSize);
486  fAveFFTPowerVec[plane]->Fill(freq, std::min(powerVec[idx],999.), 1.);
487  }
488 
489  // Idea here is to run through the power spectrum and keep a running average of the n bins around the current bin
490  size_t numBinsToAve(9); // number bins either size of current bin
491  size_t lowestBin(3); //(275); // Go no lower than this?
492 
493  size_t currentBin(halfFFTDataSize - numBinsToAve - 1);
494 
495  fWaveformTool.triangleSmooth(powerVec, powerVec);
496 
497  icarusutil::TimeVec powerDerivVec;
498 
499  fWaveformTool.firstDerivative(powerVec, powerDerivVec);
500 
501  // Find the peaks...
502  icarus_signal_processing::WaveformTools<float>::PeakTupleVec peakTupleVec;
503 
504  fWaveformTool.findPeaks(powerDerivVec.begin() + 300, powerDerivVec.end(), peakTupleVec, 10., 0);
505 
506  icarusutil::TimeVec smoothPowerVec = powerVec;
507 
508  // Try smoothing the peak regions
509  for(const auto& peakTuple : peakTupleVec)
510  {
511  if (std::get<0>(peakTuple) >= powerVec.size() || std::get<2>(peakTuple) >= powerVec.size())
512  {
513  std::cout << "indexing problem - first: " << std::get<0>(peakTuple) << ", last: " << std::get<2>(peakTuple) << std::endl;
514  continue;
515  }
516 
517  size_t firstBin = std::get<0>(peakTuple);
518  size_t lastBin = std::get<2>(peakTuple);
519  double firstBinVal = powerVec.at(firstBin);
520  double lastBinVal = powerVec.at(lastBin);
521  double stepVal = (lastBinVal - firstBinVal) / double(lastBin - firstBin);
522  double newBinVal = firstBinVal + stepVal;
523 
524  while(++firstBin < lastBin)
525  {
526  // Update the power first
527  smoothPowerVec[firstBin] = newBinVal;
528  newBinVal += stepVal;
529  }
530  }
531 
532  while(currentBin > lowestBin)
533  {
534  double avePowerThisBin(smoothPowerVec.at(currentBin));
535  double freq = 1.e6 * double(currentBin)/ (sampleRate * readOutSize);
536 
537  if (wire >= fLoWireByPlane[plane] && wire < fHiWireByPlane[plane])
538  {
539  fSmoothPowerVec[plane][wire-fLoWireByPlane[plane]]->Fill(freq, avePowerThisBin, 1.);
540  fFFTPowerDerivVec[plane][wire-fLoWireByPlane[plane]]->Fill(freq, powerDerivVec.at(currentBin), 1.);
541  }
542 
543  fAveSmoothPowerVec[plane]->Fill(freq, avePowerThisBin, 1.);
544  fAveFFTPowerDerivVec[plane]->Fill(freq, powerDerivVec.at(currentBin), 1.);
545 
546  currentBin--;
547  }
548 
549  // Recover the filter from signal shaping services...
551 
552  // Convolve this with the FFT of the input waveform
553  fFFT->convolute(inputVec,filter,0);
554  fFFT->getFFTPower(inputVec,powerVec);
555 
556  for(size_t idx = 0; idx < halfFFTDataSize; idx++)
557  {
558  double freq = 1.e6 * double(idx)/ (sampleRate * readOutSize);
559  fConvFFTPowerVec[plane]->Fill(freq, std::min(powerVec[idx],999.), 1.);
560  }
561 
562  return;
563 }
564 
565 // Useful for normalizing histograms
566 void BasicRawDigitAnalysis::endJob(int numEvents)
567 {
568  // Nothing to do if nothing was initialized
569  if (fAveFFTPowerVec.empty()) return;
570 
571  // A task to complete is to fit the average power displays with aim to develop a "good" filter function and
572  // get the signal to noise ratio
573  for(size_t planeIdx = 0; planeIdx < fGeometry.Nplanes(); planeIdx++)
574  {
575  TH1* avePowerHist = fAveFFTPowerVec[planeIdx];
576 
577  // Create the fitting function, use the histogram name to help
578  std::string funcName = std::string(avePowerHist->GetName()) + "_func";
579 
580  // Create the function object
581  TF1 fitFunc(funcName.c_str(),fFFTFitFuncVec.at(planeIdx).c_str(),avePowerHist->GetMinimum(),avePowerHist->GetMaximum());
582 
583  // Set initial parameters
584  int paramIdx(0);
585 
586  for(const auto& param : fParameterVec.at(planeIdx)) fitFunc.SetParameter(paramIdx++, param);
587 
588  int fitResult(-1);
589 
590  try
591  { fitResult = avePowerHist->Fit(&fitFunc,"QNRWB","", avePowerHist->GetMinimum(),avePowerHist->GetMaximum());}
592  catch(...)
593  {
594  std::cout << "******* FFT power vec fit failure, skipping *******" << std::endl;
595  continue;
596  }
597 
598  if (!fitResult)
599  {
600  double chi2PerNDF = (fitFunc.GetChisquare() / fitFunc.GetNDF());
601  int NDF = fitFunc.GetNDF();
602 
603  std::cout << "******************** Fit of " << avePowerHist->GetName() << " ********************" << std::endl;
604  std::cout << "-- Function: " << fFFTFitFuncVec.at(planeIdx) << ", chi2PerNDF: " << chi2PerNDF << ", NDF: " << NDF << std::endl;
605  std::cout << "-- Parameters - 0: " << fitFunc.GetParameter(0);
606 
607  for(size_t idx = 1; idx < fParameterVec.at(planeIdx).size(); idx++) std::cout << ", " << idx << ": " << fitFunc.GetParameter(idx);
608 
609  std::cout << std::endl;
610  }
611  }
612 
613  return;
614 }
615 
616 DEFINE_ART_CLASS_TOOL(BasicRawDigitAnalysis)
617 }
caldata::RawDigitCharacterizationAlg fCharacterizationAlg
std::map< raw::ChannelID_t, const sim::SimChannel * > SimChannelMap
Utilities related to art service access.
Collection of charge vs time digitized from a single readout channel.
Definition: RawDigit.h:69
icarusutil::SignalShapingICARUSService & fSignalServices
The signal shaping service.
virtual const icarusutil::FrequencyVec & getResponseVec() const =0
static constexpr Sample_t transform(Sample_t sample)
std::vector< std::vector< TProfile * > > fSmoothPowerVec
std::vector< art::Ptr< raw::RawDigit >> RawDigitPtrVec
Interface for filling histograms.
T::provider_type const * providerFrom()
Returns a constant pointer to the provider of specified service.
Definition: ServiceUtil.h:77
virtual const icarusutil::FrequencyVec & getConvKernel() const =0
walls no right
Definition: selectors.fcl:105
virtual const IFilter * getFilter() const =0
ChannelID_t Channel() const
DAQ channel this raw data was read from.
Definition: RawDigit.h:212
std::vector< geo::WireID > ChannelToWire(raw::ChannelID_t const channel) const
Returns a list of wires connected to the specified TPC channel.
std::vector< std::vector< TProfile * > > fFFTPowerVec
std::vector< ComplexVal > FrequencyVec
void configure(fhicl::ParameterSet const &pset) override
pure virtual base interface for detector clocks
const lariov::DetPedestalProvider & fPedestalRetrievalAlg
Keep track of an instance to the pedestal retrieval alg.
std::unique_ptr< icarus_signal_processing::ICARUSFFT< double >> FFTPointer
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.
icarus_signal_processing::WaveformTools< double > WaveformTools
std::vector< SigProcPrecision > TimeVec
walls no left
Definition: selectors.fcl:105
std::vector< std::vector< TProfile * > > fFFTRealVec
Description of geometry of one entire detector.
virtual float PedMean(raw::ChannelID_t ch) const =0
Retrieve pedestal information.
tuple dir
Definition: dropbox.py:28
physics filters filter
const geo::GeometryCore & fGeometry
pointer to Geometry service
raw::ChannelID_t PlaneWireToChannel(WireID const &wireid) const
Returns the ID of the TPC channel connected to the specified wire.
std::vector< std::vector< TProfile * > > fFFTImaginaryVec
void initializeHists(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, art::ServiceHandle< art::TFileService > &, const std::string &) override
Interface for initializing the histograms to be filled.
Contains all timing reference information for the detector.
std::string to_string(WindowPattern const &pattern)
void filterFFT(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, std::vector< short > &, raw::ChannelID_t, size_t, size_t, float, bool) const
std::vector< std::vector< TProfile * > > fFFTPowerDerivVec
void fillHistograms(const detinfo::DetectorClocksData &clockData, const detinfo::DetectorPropertiesData &detProp, const IRawDigitHistogramTool::RawDigitPtrVec &, const IRawDigitHistogramTool::SimChannelMap &) const override
Interface for filling histograms.
const icarus_tool::IResponse & GetResponse(size_t channel) const
std::vector< size_t > fHiWireByPlane
Hi wire for individual wire histograms.
void endJob(int numEvents) override
Interface for method to executve at the end of run processing.
art::ServiceHandle< art::TFileService > tfs
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
void Uncompress(const std::vector< short > &adc, std::vector< short > &uncompressed, raw::Compress_t compress)
Uncompresses a raw data buffer.
Definition: raw.cxx:776
BasicRawDigitAnalysis(fhicl::ParameterSet const &pset)
Constructor.
Useful definitions.
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
void getWaveformParams(const RawDigitVector &rawWaveform, unsigned int channel, unsigned int view, unsigned int wire, float &truncMean, float &truncRms, short &mean, short &median, short &mode, float &skewness, float &rms, short &minMax, float &neighborRatio, float &pedCorVal) const
std::vector< size_t > fLoWireByPlane
Low wire for individual wire histograms.
std::vector< std::vector< double > > fParameterVec
Initial parameters for fit function.
std::vector< std::string > fFFTFitFuncVec
Function definitions for fitting the average FFT power spectra.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
auto const detProp