All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FullWireDeconvolution_tool.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file FullWireDeconvolution.cc
3 /// \author T. Usher
4 ////////////////////////////////////////////////////////////////////////
5 
6 #include <cmath>
8 #include "art/Utilities/ToolMacros.h"
9 #include "art/Framework/Services/Registry/ServiceHandle.h"
10 #include "art_root_io/TFileService.h"
11 #include "messagefacility/MessageLogger/MessageLogger.h"
12 #include "cetlib_except/exception.h"
15 #include "larcore/CoreUtils/ServiceUtil.h" // lar::providerFrom()
17 
18 #include "art/Utilities/make_tool.h"
19 #include "icarus_signal_processing/WaveformTools.h"
20 #include "icarus_signal_processing/Filters/ICARUSFFT.h"
21 
22 #include "TH1D.h"
23 
24 #include <fstream>
25 
26 namespace icarus_tool
27 {
28 
30 {
31 public:
32  explicit FullWireDeconvolution(const fhicl::ParameterSet& pset);
33 
35 
36  void configure(const fhicl::ParameterSet& pset) override;
37  void initializeHistograms(art::TFileDirectory&) const override;
38 
39  void Deconvolve(IROIFinder::Waveform const&,
40  double samplingRate,
43  recob::Wire::RegionsOfInterest_t& ) const override;
44 
45 private:
46 
47  // Member variables from the fhicl file
48  bool fDodQdxCalib; ///< Do we apply wire-by-wire calibration?
49  std::string fdQdxCalibFileName; ///< Text file for constants to do wire-by-wire calibration
50  std::map<unsigned int, float> fdQdxCalib; ///< Map to do wire-by-wire calibration, key is channel
51 
52  icarus_signal_processing::WaveformTools<float> fWaveformTool;
53 
54  std::unique_ptr<icarus_signal_processing::ICARUSFFT<double>> fFFT; ///< Object to handle thread safe FFT
55 
56  const geo::GeometryCore* fGeometry = lar::providerFrom<geo::Geometry>();
57  art::ServiceHandle<icarusutil::SignalShapingICARUSService> fSignalShaping;
58 };
59 
60 //----------------------------------------------------------------------
61 // Constructor.
62 FullWireDeconvolution::FullWireDeconvolution(const fhicl::ParameterSet& pset)
63 {
64  configure(pset);
65 }
66 
68 {
69 }
70 
71 void FullWireDeconvolution::configure(const fhicl::ParameterSet& pset)
72 {
73  // Start by recovering the parameters
74  //wire-by-wire calibration
75  fDodQdxCalib = pset.get< bool >("DodQdxCalib", false);
76 
77  if (fDodQdxCalib)
78  {
79  fdQdxCalibFileName = pset.get< std::string >("dQdxCalibFileName");
80  std::string fullname;
81  cet::search_path sp("FW_SEARCH_PATH");
82  sp.find_file(fdQdxCalibFileName, fullname);
83 
84  if (fullname.empty())
85  {
86  std::cout << "Input file " << fdQdxCalibFileName << " not found" << std::endl;
87  throw cet::exception("File not found");
88  }
89  else
90  std::cout << "Applying wire-by-wire calibration using file " << fdQdxCalibFileName << std::endl;
91 
92  std::ifstream inFile(fullname, std::ios::in);
93  std::string line;
94 
95  while (std::getline(inFile,line))
96  {
97  unsigned int channel;
98  float constant;
99  std::stringstream linestream(line);
100  linestream >> channel >> constant;
101  fdQdxCalib[channel] = constant;
102  if (channel%1000==0) std::cout<<"Channel "<<channel<<" correction factor "<<fdQdxCalib[channel]<<std::endl;
103  }
104  }
105 
106  // Get signal shaping service.
107  fSignalShaping = art::ServiceHandle<icarusutil::SignalShapingICARUSService>();
108 
109  // Now set up our plans for doing the convolution
110  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataForJob();
111  fFFT = std::make_unique<icarus_signal_processing::ICARUSFFT<double>>(detProp.NumberTimeSamples());
112 
113  return;
114 }
115 
117  double const samplingRate,
118  raw::ChannelID_t channel,
119  IROIFinder::CandidateROIVec const& roiVec,
120  recob::Wire::RegionsOfInterest_t& ROIVec) const
121 {
122  // The goal of this function is to reproduce "exactly" the operation of the deconvolution process in MCC7
123  // hence the copying over of some of the code that has been pushed into external tools.
124 
125  // The size of the input waveform **should** be the raw buffer size
126  size_t dataSize = waveform.size();
127 
128  // Make sure the deconvolution size is set correctly (this will probably be a noop after first call)
129  fSignalShaping->SetDecon(samplingRate, dataSize, channel);
130 
131  // now make a buffer to contain the waveform which will be of the right size
132  icarusutil::TimeVec rawAdcLessPedVec(dataSize,0.);
133 
134  size_t binOffset = 0; //transformSize > dataSize ? (transformSize - dataSize) / 2 : 0;
135  float deconNorm = fSignalShaping->GetDeconNorm();
136  float normFactor = 1. / deconNorm; // This is what we had previously: (samplingRate * deconNorm);
137  bool applyNormFactor = std::abs(normFactor - 1.) > std::numeric_limits<float>::epsilon() ? true : false;
138 
139  // Copy the input (assumed pedestal subtracted) waveforms into our zero padded deconvolution buffer
140  std::copy(waveform.begin(),waveform.end(),rawAdcLessPedVec.begin()+binOffset);
141 
142  // Strategy is to run deconvolution on the entire channel and then pick out the ROI's we found above
143  fFFT->deconvolute(rawAdcLessPedVec, fSignalShaping->GetResponse(channel).getDeconvKernel(), fSignalShaping->ResponseTOffset(channel));
144 
145  std::vector<float> holder;
146 
147  for(size_t roiIdx = 0; roiIdx < roiVec.size(); roiIdx++)
148  {
149  const auto& roi = roiVec[roiIdx];
150 
151  // First up: copy out the relevent ADC bins into the ROI holder
152  size_t roiLen = roi.second - roi.first + 1;
153 
154  holder.resize(roiLen);
155 
156  std::copy(rawAdcLessPedVec.begin()+binOffset+roi.first, rawAdcLessPedVec.begin()+binOffset+roiLen, holder.begin());
157  if (applyNormFactor) std::transform(holder.begin(),holder.end(),holder.begin(), std::bind(std::multiplies<float>(),std::placeholders::_1,normFactor));
158 
159  // Get the truncated mean and rms
160  float truncMean;
161  int nTrunc;
162  int range;
163 
164  fWaveformTool.getTruncatedMean(holder, truncMean, nTrunc, range);
165 
166  std::transform(holder.begin(),holder.end(),holder.begin(), std::bind(std::minus<float>(),std::placeholders::_1,truncMean));
167 
168  // apply wire-by-wire calibration
169  if (fDodQdxCalib){
170  if(fdQdxCalib.find(channel) != fdQdxCalib.end()){
171  float constant = fdQdxCalib.at(channel);
172  //std::cout<<channel<<" "<<constant<<std::endl;
173  for (size_t iholder = 0; iholder < holder.size(); ++iholder){
174  holder[iholder] *= constant;
175  }
176  }
177  }
178 
179  // add the range into ROIVec
180  ROIVec.add_range(roi.first, std::move(holder));
181  }
182 
183  return;
184 }
185 
186 void FullWireDeconvolution::initializeHistograms(art::TFileDirectory& histDir) const
187 {
188  // It is assumed that the input TFileDirectory has been set up to group histograms into a common
189  // folder at the calling routine's level. Here we create one more level of indirection to keep
190  // histograms made by this tool separate.
191 /*
192  std::string dirName = "FullWireDeconvolutionPlane_" + std::to_string(fPlane);
193 
194  art::TFileDirectory dir = histDir.mkdir(dirName.c_str());
195 
196  auto const* detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
197  double samplingRate = detprop->SamplingRate();
198  double numBins = fFullWireDeconvolutionVec.size();
199  double maxFreq = 500. / samplingRate;
200  std::string histName = "FullWireDeconvolutionPlane_" + std::to_string(fPlane);
201 
202  TH1D* hist = dir.make<TH1D>(histName.c_str(), "FullWireDeconvolution;Frequency(MHz)", numBins, 0., maxFreq);
203 
204  for(int bin = 0; bin < numBins; bin++)
205  {
206  double freq = maxFreq * double(bin + 0.5) / double(numBins);
207 
208  hist->Fill(freq, fFullWireDeconvolutionVec.at(bin).Re());
209  }
210 */
211 
212  return;
213 }
214 
215 DEFINE_ART_CLASS_TOOL(FullWireDeconvolution)
216 }
Utilities related to art service access.
static constexpr Sample_t transform(Sample_t sample)
This provides an interface for tools which are tasked with running the deconvolution algorithm...
void Deconvolve(IROIFinder::Waveform const &, double samplingRate, raw::ChannelID_t, IROIFinder::CandidateROIVec const &, recob::Wire::RegionsOfInterest_t &) const override
const datarange_t & add_range(size_type offset, ITER first, ITER last)
Adds a sequence of elements as a range with specified offset.
void initializeHistograms(art::TFileDirectory &) const override
std::map< unsigned int, float > fdQdxCalib
Map to do wire-by-wire calibration, key is channel.
TString inFile
T abs(T value)
std::string fdQdxCalibFileName
Text file for constants to do wire-by-wire calibration.
std::vector< SigProcPrecision > TimeVec
FullWireDeconvolution(const fhicl::ParameterSet &pset)
Description of geometry of one entire detector.
bool fDodQdxCalib
Do we apply wire-by-wire calibration?
art::ServiceHandle< icarusutil::SignalShapingICARUSService > fSignalShaping
icarus_signal_processing::WaveformTools< float > fWaveformTool
if &&[-z"$BASH_VERSION"] then echo Attempting to switch to bash bash shellSwitch exit fi &&["$1"= 'shellSwitch'] shift declare a IncludeDirectives for Dir in
void configure(const fhicl::ParameterSet &pset) override
T copy(T const &v)
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
std::unique_ptr< icarus_signal_processing::ICARUSFFT< double > > fFFT
Object to handle thread safe FFT.
art framework interface to geometry description
BEGIN_PROLOG could also be cout
auto const detProp