Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HitRebuilderByFit.h
Go to the documentation of this file.
1 /*
2  * HitRebuilderByFit.h
3  * Class that rebuild the TAC time using 5-parameter fit.
4  * the meaning of the parameters are fixed since this class
5  * needs to provide the initial values for the parameters.
6  * The template argument is the functor that will calculate the
7  * value of the pulse distribution for a given set of five parameters.
8  * Created on: Jun 8, 2017
9  * Author: Hovanes Egiyan
10  */
11 
12 #ifndef LIBRARIES_TAC_HITREBUILDERBYFIT_H_
13 #define LIBRARIES_TAC_HITREBUILDERBYFIT_H_
14 
15 #include <vector>
16 #include <set>
17 #include <string>
18 #include <functional>
19 #include <iostream>
20 #include <stdexcept>
21 
22 #include <TH1D.h>
23 #include <TF1.h>
24 #include <TFitResult.h>
25 #include <TFitResultPtr.h>
26 #include <TCanvas.h>
27 
28 #include <JANA/JFactory.h>
29 #include <DAQ/Df250WindowRawData.h>
30 
31 #include "DTACDigiHit.h"
32 #include "DTACTDCDigiHit.h"
33 #include "DTACHit.h"
34 
35 #include <TAC/HitRebuilderTAC.h>
36 
37 template<typename F>
39 protected:
40  std::function<double(const double *data, const Double_t *param)> waveFunction =
41  F();
42  double adcPedestal = 100.0;
43  double riseTime = 0.8;
44  double decayTime = 2.6;
45  TF1* fitFun = nullptr;
46 public:
47  HitRebuilderByFit( jana::JEventLoop* eventLoop) :
48  HitRebuilderTAC(eventLoop) {
49 
50  HitRebuilderByFit::readCCDB( eventLoop );
51  // Create ROOT function for the fit using the functor
52  std::string funName = this->getTagString() + ":fitFun";
53  fitFun = new TF1(funName.c_str(), waveFunction, 5, 70, 5);
54  fitFun->Print();
55  std::cout << "ROOT function pointer is " << fitFun << std::endl;
56  }
57 
60  fitFun = dynamic_cast<TF1*>(b.fitFun->Clone());
61  }
63  if (&b != this) {
64  *(dynamic_cast<HitRebuilderTAC*>(this)) =
65  *(dynamic_cast<HitRebuilderTAC*>(&b));
66  }
67  return *this;
68  }
69  virtual ~HitRebuilderByFit() {
70  std::cout << "In ~HitRebuilderByFit" << std::endl;
71  if (fitFun != nullptr)
72  delete fitFun;
73  }
74 
75  jerror_t readCCDB(jana::JEventLoop *eventLoop);
76 
77  virtual double getTimeFromRawData(const vector<uint16_t>& samples) override;
78 
80  return "REBUILD_" + F::getTagString();
81  }
82 
83  double getDecayTime() const {
84  return decayTime;
85  }
86 
87  void setDecayTime(double decayTime = 2.6) {
88  this->decayTime = decayTime;
89  }
90 
91  double getRiseTime() const {
92  return riseTime;
93  }
94 
95  void setRiseTime(double riseTime = 0.8) {
96  this->riseTime = riseTime;
97  }
98 
99  const TF1* getFitFun() {
100  return fitFun;
101  }
102 
103  const std::function<double(const double* data, const Double_t* param)>& getWaveFunction() const {
104  return waveFunction;
105  }
106 };
107 
108 template<typename F>
109 inline jerror_t HitRebuilderByFit<F>::readCCDB(jana::JEventLoop* eventLoop) {
110  std::cout << "In HitRebuilderByFit::readCCDB() , reading calibration constants" << std::endl;
111 
112  // First re-read the constants for the base class. This is not a virtual method since it is
113  // usually being called from the constructor.
114  HitRebuilderTAC::readCCDB( eventLoop );
115 
116  // a_pedestals (pedestals)
117  if (eventLoop->GetCalib("/TAC/pedestals", adcPedestal))
118  jout << "Error loading /TAC/pedestals !" << std::endl;
119 
120 
121  map<string, double> pulseShapeParameter;
122  if (eventLoop->GetCalib("/TAC/pulse_shape", pulseShapeParameter))
123  jout << "Error loading /TAC/pulse_shape !" << std::endl;
124 
125  // riseTime (riseTime)
126  if (pulseShapeParameter.find("riseTime") != pulseShapeParameter.end())
127  riseTime = pulseShapeParameter["riseTime"];
128  else
129  jerr << "Unable to get riseTime from /TAC/pulse_shape !" << std::endl;
130  // decayTime (decayTime)
131  if (pulseShapeParameter.find("decayTime") != pulseShapeParameter.end())
132  decayTime = pulseShapeParameter["decayTime"];
133  else
134  jerr << "Unable to get decayTime from /TAC/pulse_shape !" << std::endl;
135 
136 
137  std::cout << "riseTime is " << riseTime << " , decayTime is " << decayTime <<
138  " , adcPedestal is " << adcPedestal << std::endl;
139 
140  return NOERROR;
141 }
142 
143 template<typename F>
145  const vector<uint16_t>& samples) {
146 
147 // Create the histogram for fitting
148  string histoName = this->getTagString() + ":sample";
149  string histoTitle = string(
150  " FADC samples for TAC for builder " + getTagString());
151  TH1D sampleHisto(histoName.c_str(), histoTitle.c_str(), samples.size(), 0.0,
152  double(samples.size()));
153  int iBin = 1;
154  for (auto& sample : samples) {
155  sampleHisto.SetBinContent(iBin, double(sample));
156  sampleHisto.SetBinError(iBin, 1.0);
157  iBin++;
158  }
159  // Find the maximum by going through the raw data and comparing samples
160  pair<double, double> maxInfo(0, 0);
161  auto maxElementIter = std::max_element(samples.begin(), samples.end());
162  double peakLocation = std::distance(samples.begin(), maxElementIter);
163 
164 // double pedestal = 101.0;
165  double amplitude = *maxElementIter - adcPedestal;
166  fitFun->SetParNames("Pedestal", "PeakLocation", "riseTime", "Amplitude",
167  "Lambda");
168 
169 // std::cout << "Pedestal is " << adcPedestal << " peak is at " << peakLocation
170 // << " amplitude is at " << amplitude << " lambda is " << lambda
171 // << std::endl;
172  fitFun->SetParameters(adcPedestal, peakLocation, amplitude, amplitude,
173  decayTime);
174 
175  // std::cout << "Set parameters" << std::endl;
176  double xMin = fitFun->GetXmin();
177  double xMax = peakLocation + 2 * decayTime;
178 // std::cout << "Function peak is at " << fitFun->Eval(peakLocation)
179 // << std::cout;
180 //
181 // std::cout << "Will try to fit from " << xMin << " to " << xMax
182 // << " using TF1 at " << fitFun << std::endl;
183 
184  fitFun->FixParameter(0, adcPedestal);
185  fitFun->FixParameter(2, riseTime);
186  fitFun->FixParameter(4, decayTime);
187  TFitResultPtr fitResultPtr = sampleHisto.Fit(fitFun, "WWQ0S", "", xMin,
188  xMax);
189  double newPeak = fitFun->GetParameter(1);
190 
191  double pulseTime = timeScaleADC * newPeak - adcTimeOffset + timeBaseADC;
192 
193  if (!fitResultPtr->IsValid()) {
194  std::string errMsg = "Fit failed in " + this->getTagString();
195  throw std::runtime_error(errMsg);
196  // std::cout << "Failed fit " << std::endl;
197 // std::cout << " Convergence status is " << fitResultPtr->Status() << std::endl;
198 //// TCanvas c();
199 //// sampleHisto.Draw();
200 //// usleep(2000000);
201  }
202 
203 // int fitConvergenceStatus = fitResultPtr.Get()->Status();
204 //
205 // if( fitConvergenceStatus < 2 )
206 // std::cout << "Convergence status is " << fitConvergenceStatus << std::endl;
207 //
208 // std::cout << "Convergence status is " << fitConvergenceStatus << std::endl;
209  return pulseTime;
210 }
211 
212 #endif /* LIBRARIES_TAC_HITREBUILDERBYFIT_H_ */
#define F(x, y, z)
jerror_t readCCDB(jana::JEventLoop *eventLoop)
void setRiseTime(double riseTime=0.8)
const std::function< double(const double *data, const Double_t *param)> & getWaveFunction() const
jerror_t readCCDB(jana::JEventLoop *eventLoop)
char string[256]
double getDecayTime() const
double getRiseTime() const
HitRebuilderByFit(jana::JEventLoop *eventLoop)
void setDecayTime(double decayTime=2.6)
std::function< double(const double *data, const Double_t *param)> waveFunction
HitRebuilderByFit & operator=(const HitRebuilderByFit &b)
virtual ~HitRebuilderByFit()
HitRebuilderByFit(const HitRebuilderByFit &b)
virtual double getTimeFromRawData(const vector< uint16_t > &samples) override
const TF1 * getFitFun()
static std::string getTagString()