All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FieldResponse_tool.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 /// \file FieldResponse.cc
3 /// \author T. Usher
4 ////////////////////////////////////////////////////////////////////////
5 
6 #include <cmath>
7 #include "IFieldResponse.h"
8 #include "art/Utilities/ToolMacros.h"
9 #include "art/Utilities/make_tool.h"
10 #include "art_root_io/TFileService.h"
11 #include "messagefacility/MessageLogger/MessageLogger.h"
12 #include "cetlib_except/exception.h"
14 #include "art_root_io/TFileService.h"
16 #include "icarus_signal_processing/Filters/ICARUSFFT.h"
17 #include "icarus_signal_processing/WaveformTools.h"
18 #include "TFile.h"
19 #include "TProfile.h"
20 
21 #include <fstream>
22 #include <iomanip>
23 
24 namespace icarus_tool
25 {
26 
28 {
29 public:
30  explicit FieldResponse(const fhicl::ParameterSet& pset);
31 
33 
34  void configure(const fhicl::ParameterSet&) override;
35  void setResponse(double, double, double) override;
36  void outputHistograms(art::TFileDirectory&) const override;
37 
38  size_t getPlane() const override;
39  size_t getResponseType() const override;
40  size_t getNumBins() const override;
41  double getBinCenter(int bin) const override;
42  double getBinContent(int bin) const override;
43  double getLowEdge() const override;
44  double getHighEdge() const override;
45  double getBinWidth() const override;
46  double getTOffset() const override;
47  double getIntegral() const override;
48  double interpolate(double x) const override;
49 
50  const icarusutil::TimeVec& getResponseVec() const override {return fFieldResponseVec;}
52 
53 private:
54  // Utility routine for converting numbers to strings
55  std::string numberToString(int number);
56 
57  // Make sure we have been initialized
58  bool fIsValid;
59 
60  // Member variables from the fhicl file
61  size_t fThisPlane;
62  size_t fResponseType;
69 
70  // Pointer to the input histogram
72 
73  // Container for the field response "function"
75 
76  // And a container for the FFT of the above
78 
79  // Derived variables
80  double fT0Offset;
81 
82  // Keep track of the FFT
83  std::unique_ptr<icarus_signal_processing::ICARUSFFT<double>> fFFT; ///< Object to handle thread safe FFT
84 };
85 
86 //----------------------------------------------------------------------
87 // Constructor.
88 FieldResponse::FieldResponse(const fhicl::ParameterSet& pset) :
89  fIsValid(false), fSignalType(geo::kMysteryType), fFFT(nullptr)
90 {
91  configure(pset);
92 }
93 
94 void FieldResponse::configure(const fhicl::ParameterSet& pset)
95 {
96  // Start by recovering the parameters
97  fThisPlane = pset.get< size_t >("Plane");
98  fResponseType = pset.get< size_t >("ResponseType");
99  fSignalType = pset.get< size_t >("SignalType") == 0 ? geo::kInduction : geo::kCollection;
100  fFieldResponseFileName = pset.get< std::string >("FieldResponseFileName");
101  fFieldResponseFileVersion = pset.get< std::string >("FieldResponseFileVersion");
102  fFieldResponseHistName = pset.get< std::string >("FieldResponseHistName");
103  fFieldResponseAmplitude = pset.get< double >("FieldResponseAmplitude");
104  fTimeCorrectionFactor = pset.get< double >("TimeCorrectionFactor");
105 
106  // Recover the input field response histogram
107 // std::string fileName = fFieldResponseFileName + "_vw" + numberToString(fThisPlane) + "_" + fFieldResponseFileVersion + ".root";
108  std::string fileName = fFieldResponseFileName + "_vw" + numberToString(fResponseType) + "_" + fFieldResponseFileVersion + ".root";
109 
110  std::string fullFileName;
111  cet::search_path searchPath("FW_SEARCH_PATH");
112 
113  std::cout << "************************** Field Response Plane " << fThisPlane << " type: " << fResponseType << " *****************************" << std::endl;
114  std::cout << "FileName: " << fullFileName << std::endl;
115 
116  if (!searchPath.find_file(fileName, fullFileName))
117  throw cet::exception("FieldResponse::configure") << "Can't find input file: '" << fileName << "'\n";
118 
119  TFile inputFile(fullFileName.c_str(), "READ");
120 
121  if (!inputFile.IsOpen())
122  throw cet::exception("FieldResponse::configure") << "Unable to open input file: " << fileName << std::endl;
123 
124 // std::string histName = fFieldResponseHistName + "_vw" + numberToString(fThisPlane) + "_" + fFieldResponseFileVersion + ".root";
125  std::string histName = fFieldResponseHistName + "_vw" + numberToString(fResponseType) + "_" + fFieldResponseFileVersion + ".root";
126 
127  std::cout << "HistFile: " << histName << std::endl;
128 
129  fFieldResponseHist = (TH1D*)((TH1D*)inputFile.Get(histName.c_str()))->Clone();
130 
131  fFieldResponseHist->SetDirectory(nullptr);
132 
133  inputFile.Close();
134 
135  // Calculation of the T0 offset depends on the signal type
136  int binOfInterest = fFieldResponseHist->GetMinimumBin();
137 
138  // For collection planes it is as simple as finding the maximum bin
139  if (fSignalType == geo::kCollection) binOfInterest = fFieldResponseHist->GetMaximumBin();
140 
141  // Do a backwards search to find the first positive bin
142  while(1)
143  {
144  // Did we go too far?
145  if (binOfInterest < 0)
146  {
147  std::cout << "Cannot find zero-point crossover for induction response! Plane:" << fThisPlane << ", signal type: " << fSignalType << ", response type: " << fResponseType << std::endl;
148  throw cet::exception("FieldResponse::configure") << "Cannot find zero-point crossover for induction response! Plane:" << fThisPlane << ", signal type: " << fSignalType << ", response type: " << fResponseType << std::endl;
149  }
150 
151  double content = fFieldResponseHist->GetBinContent(binOfInterest);
152 
153  if (content >= 0.) break;
154 
155  binOfInterest--;
156  }
157 
158  fT0Offset = -(fFieldResponseHist->GetXaxis()->GetBinCenter(binOfInterest) - fFieldResponseHist->GetXaxis()->GetBinCenter(1)) * fTimeCorrectionFactor;
159 
160  fIsValid = true;
161 
162  // Hoops to jump throught to find "correct" size for FFT
163  // Find the next power of 2 that is larger than the vector we have
164  size_t newVecSize(64);
165 
166  while(getNumBins() > newVecSize) newVecSize *= 2;
167 
168  // Check that we have initialized our FFT object
169  fFFT = std::make_unique<icarus_signal_processing::ICARUSFFT<double>>(newVecSize);
170 
171  double integral = getIntegral();
172 
173  std::cout << "--> Plane: " << fThisPlane << ", integral: " << integral << std::endl;
174 
175  return;
176 }
177 
178 void FieldResponse::setResponse(double weight, double correction3D, double timeScaleFctr)
179 {
180  // This sets the field response in the time domain
181  double timeFactor = correction3D * timeScaleFctr;
182  size_t numBins = getNumBins();
183  size_t nResponseBins = numBins * timeFactor;
184 
185  fFieldResponseVec.resize(nResponseBins);
186 
187  double x0 = getBinCenter(1);
188  double deltaX = fFieldResponseHist->GetBinWidth(1); // This gets returned in us
189 
190  for(size_t bin = 1; bin <= nResponseBins; bin++)
191  {
192  double xVal = x0 + deltaX * (bin-1) / timeFactor;
193 
195  }
196 
197  // Find the next power of 2 that is larger than the vector we have
198  size_t newVecSize(64);
199 
200  while(fFieldResponseVec.size() > newVecSize) newVecSize *= 2;
201 
202  // Resize and pad with zeroes
203  fFieldResponseVec.resize(newVecSize,0.);
204 
205  fFieldResponseFFTVec.resize(newVecSize);
206 
208 
209  return;
210 }
211 
212 void FieldResponse::outputHistograms(art::TFileDirectory& histDir) const
213 {
214  // It is assumed that the input TFileDirectory has been set up to group histograms into a common
215  // folder at the calling routine's level. Here we create one more level of indirection to keep
216  // histograms made by this tool separate.
217  art::TFileDirectory dir = histDir.mkdir(fFieldResponseHistName.c_str());
218 
219  TProfile* hist = dir.make<TProfile>(fFieldResponseHistName.c_str(), "Field Response; Time(us)", getNumBins(), getLowEdge(), getHighEdge());
220 
221  double binWidth = getBinWidth() / fTimeCorrectionFactor;
222 
223  std::vector<double> histResponseVec(getNumBins());
224 
225  for(size_t idx = 0; idx < getNumBins(); idx++)
226  {
227  double xBin = getLowEdge() + idx * binWidth;
228  double binVal = fFieldResponseHist->GetBinContent(idx);
229 
230  hist->Fill(xBin, binVal, 1.);
231  histResponseVec.at(idx) = binVal;
232  }
233 
234  // Grab some useful tools
235  icarus_signal_processing::WaveformTools<double> waveformTool;
236 
237  // Make a copy of the response vec
238  std::vector<double> smoothedResponseVec;
239 
240  // Run the triangulation smoothing
241  waveformTool.triangleSmooth(histResponseVec, smoothedResponseVec);
242 
243  // Now make histogram of this
244  std::string histName = "Smooth_" + fFieldResponseHistName;
245 
246  TProfile* smoothHist = dir.make<TProfile>(histName.c_str(), "Field Response; Time(us)", getNumBins(), getLowEdge(), getHighEdge());
247 
248  for(size_t idx = 0; idx < smoothedResponseVec.size(); idx++)
249  {
250  double xBin = getLowEdge() + idx * binWidth;
251 
252  smoothHist->Fill(xBin,smoothedResponseVec.at(idx), 1.);
253  }
254 
255  // Get the FFT of the response
256  size_t halfFFTDataSize(fFieldResponseFFTVec.size()/2);
257 
258  std::vector<double> powerVec(halfFFTDataSize);
259 
260  std::transform(fFieldResponseFFTVec.begin(), fFieldResponseFFTVec.begin() + halfFFTDataSize, powerVec.begin(), [](const auto& val){return std::abs(val);});
261 
262  // Now we can plot this...
263  double maxFreq = 0.5 / binWidth; // binWidth will be in us, maxFreq will be units of MHz
264  double freqWidth = maxFreq / powerVec.size();
265 
266  histName = "FFT_" + fFieldResponseHistName;
267 
268  TProfile* fftHist = dir.make<TProfile>(histName.c_str(), "Field Response FFT; Frequency(MHz)", powerVec.size(), 0., maxFreq);
269 
270  for(size_t idx = 0; idx < powerVec.size(); idx++)
271  {
272  double bin = (idx + 0.5) * freqWidth;
273 
274  fftHist->Fill(bin, powerVec.at(idx), 1.);
275  }
276 
277  return;
278 }
279 
281 {
282  if (!fIsValid)
283  throw cet::exception("FieldResponse::getPlane") << "Attempting to access plane info when tool is invalid state" << std::endl;
284 
285  return fThisPlane;
286 }
287 
289 {
290  if (!fIsValid)
291  throw cet::exception("FieldResponse::getResponseType") << "Attempting to access response info when tool is invalid state" << std::endl;
292 
293  return fResponseType;
294 }
295 
297 {
298  if (!fIsValid)
299  throw cet::exception("FieldResponse::getPlane") << "Attempting to access plane info when tool is invalid state" << std::endl;
300 
301  return fFieldResponseHist->GetXaxis()->GetNbins();
302 }
303 
305 {
306  if (!fIsValid)
307  throw cet::exception("FieldResponse::getPlane") << "Attempting to access plane info when tool is invalid state" << std::endl;
308 
309  return fFieldResponseHist->GetBinCenter(1) - 0.5 * fFieldResponseHist->GetBinWidth(1);
310 }
311 
313 {
314  if (!fIsValid)
315  throw cet::exception("FieldResponse::getPlane") << "Attempting to access plane info when tool is invalid state" << std::endl;
316 
317  return fFieldResponseHist->GetBinCenter(bin);
318 }
319 
321 {
322  if (!fIsValid)
323  throw cet::exception("FieldResponse::getPlane") << "Attempting to access plane info when tool is invalid state" << std::endl;
324 
325  return fFieldResponseHist->GetBinContent(bin);
326 }
327 
329 {
330  if (!fIsValid)
331  throw cet::exception("FieldResponse::getPlane") << "Attempting to access plane info when tool is invalid state" << std::endl;
332 
333  size_t nBins = getNumBins();
334 
335  return fFieldResponseHist->GetBinCenter(nBins) + 0.5 * fFieldResponseHist->GetBinWidth(nBins);
336 }
337 
339 {
340  if (!fIsValid)
341  throw cet::exception("FieldResponse::getPlane") << "Attempting to access plane info when tool is invalid state" << std::endl;
342 
343  return fFieldResponseHist->GetBinWidth(1) * fTimeCorrectionFactor;
344 }
345 
347 {
348  if (!fIsValid)
349  throw cet::exception("FieldResponse::getPlane") << "Attempting to access plane info when tool is invalid state" << std::endl;
350 
351  return fT0Offset;
352 }
353 
355 {
356  if (!fIsValid)
357  throw cet::exception("FieldResponse::getPlane") << "Attempting to access plane info when tool is invalid state" << std::endl;
358 
359  return fFieldResponseHist->Integral();
360 }
361 
362 double FieldResponse::interpolate(double x) const
363 {
364  if (!fIsValid)
365  throw cet::exception("FieldResponse::getPlane") << "Attempting to access plane info when tool is invalid state" << std::endl;
366 
367  Double_t intVal = fFieldResponseHist->Interpolate(x);
368 
369  return intVal; //fFieldResponseHist->Interpolate(x);
370 }
371 
372 std::string FieldResponse::numberToString(int number)
373 {
374  std::ostringstream string;
375 
376  string << std::setfill('0') << std::setw(2) << number;
377 
378  return string.str();
379 }
380 
381 
382 DEFINE_ART_CLASS_TOOL(FieldResponse)
383 }
double interpolate(double x) const override
std::unique_ptr< icarus_signal_processing::ICARUSFFT< double > > fFFT
Object to handle thread safe FFT.
Utilities related to art service access.
Who knows?
Definition: geo_types.h:147
static constexpr Sample_t transform(Sample_t sample)
process_name opflash particleana ie x
std::string numberToString(int number)
void setResponse(double, double, double) override
icarusutil::TimeVec fFieldResponseVec
std::vector< ComplexVal > FrequencyVec
constexpr details::BinObj< T > bin(T value)
Returns a wrapper to print the specified data in binary format.
double getLowEdge() const override
T abs(T value)
Signal from induction planes.
Definition: geo_types.h:145
double getBinCenter(int bin) const override
enum geo::_plane_sigtype SigType_t
void configure(const fhicl::ParameterSet &) override
double getTOffset() const override
std::vector< SigProcPrecision > TimeVec
double getHighEdge() const override
size_t getNumBins() const override
size_t getResponseType() const override
Definition of data types for geometry description.
tuple dir
Definition: dropbox.py:28
void outputHistograms(art::TFileDirectory &) const override
const icarusutil::TimeVec & getResponseVec() const override
double getBinContent(int bin) const override
FieldResponse(const fhicl::ParameterSet &pset)
double getBinWidth() const override
icarusutil::FrequencyVec fFieldResponseFFTVec
size_t getPlane() const override
This is the interface class for a tool to handle the field response It is assumed that the field resp...
BEGIN_PROLOG could also be cout
const icarusutil::FrequencyVec & getResponseFFTVec() const override
double getIntegral() const override
Signal from collection planes.
Definition: geo_types.h:146