Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CaloWaveformFitting.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file CaloWaveformFitting.cc
1 #include "CaloWaveformFitting.h"
2 
3 #include <TF1.h>
4 #include <TFile.h>
5 #include <TProfile.h>
6 #include <TSpline.h>
7 
8 #include <Fit/BinData.h>
9 #include <Fit/Chi2FCN.h>
10 #include <Fit/Fitter.h>
11 #include <Fit/UnBinData.h>
12 #include <HFitInterface.h>
13 #include <Math/WrappedMultiTF1.h>
14 #include <Math/WrappedTF1.h>
15 #include <ROOT/TThreadExecutor.hxx>
16 #include <ROOT/TThreadedObject.hxx>
17 
18 #include <pthread.h>
19 #include <iostream>
20 #include <string>
21 
22 
23 ROOT::TThreadExecutor *t = new ROOT::TThreadExecutor(1);
24 double CaloWaveformFitting::template_function(double *x, double *par)
25 {
26  Double_t v1 = par[0] * h_template->Interpolate(x[0] - par[1]) + par[2];
27  return v1;
28 }
29 
31 {
32  TFile *fin = TFile::Open(templatefile.c_str());
33  assert(fin);
34  assert(fin->IsOpen());
35  h_template = static_cast<TProfile *>(fin->Get("waveform_template"));
36  m_peakTimeTemp = h_template->GetBinCenter(h_template->GetMaximumBin());
37  t = new ROOT::TThreadExecutor(_nthreads);
38 }
39 
40 std::vector<std::vector<float>> CaloWaveformFitting::process_waveform(std::vector<std::vector<float>> waveformvector)
41 {
42  int size1 = waveformvector.size();
43  std::vector<std::vector<float>> fitresults;
44  for (int i = 0; i < size1; i++)
45  {
46  waveformvector.at(i).push_back(i);
47  }
48  fitresults = calo_processing_templatefit(waveformvector);
49  return fitresults;
50 }
51 
52 std::vector<std::vector<float>> CaloWaveformFitting::calo_processing_templatefit(std::vector<std::vector<float>> chnlvector)
53 {
54  auto func = [&](std::vector<float> &v)
55  {
56  int size1 = v.size() - 1;
57  if (size1 == _nzerosuppresssamples)
58  {
59  v.push_back(v.at(1) - v.at(0)); //returns peak sample - pedestal sample
60  v.push_back(-1); // set time to -1 to indicate zero suppressed
61  v.push_back(v.at(0));
62  v.push_back(0);
63  }
64  else
65  {
66  float maxheight = 0;
67  int maxbin = 0;
68  for (int i = 0; i < size1; i++)
69  {
70  if (v.at(i) > maxheight)
71  {
72  maxheight = v.at(i);
73  maxbin = i;
74  }
75  }
76  float pedestal = 1500;
77  if (maxbin > 4)
78  {
79  pedestal = 0.5 * (v.at(maxbin - 4) + v.at(maxbin - 5));
80  }
81  else if (maxbin > 3)
82  {
83  pedestal = (v.at(maxbin - 4));
84  }
85  else
86  {
87  pedestal = 0.5 * (v.at(size1 - 3) + v.at(size1 - 2));
88  }
89 
90  if (_bdosoftwarezerosuppression && maxheight - pedestal < _nsoftwarezerosuppression)
91  {
92  // std::cout << "software zero suppression happened " << std::endl;
93  v.push_back(v.at(6) - v.at(0));
94  v.push_back(-1);
95  v.push_back(v.at(0));
96  v.push_back(0);
97  }
98  else
99  {
100  auto h = new TH1F(Form("h_%d", (int) round(v.at(size1))), "", size1, -0.5, size1 - 0.5);
101  for (int i = 0; i < size1; i++)
102  {
103  h->SetBinContent(i + 1, v.at(i));
104  h->SetBinError(i + 1, 1);
105  }
106  auto f = new TF1(Form("f_%d", (int) round(v.at(size1))), this,&CaloWaveformFitting::template_function, 0, 31, 3,"CaloWaveformFitting","template_function");
107  ROOT::Math::WrappedMultiTF1 *fitFunction = new ROOT::Math::WrappedMultiTF1(*f, 3);
108  ROOT::Fit::BinData data(v.size() - 1, 1);
109  ROOT::Fit::FillData(data, h);
110  ROOT::Fit::Chi2Function *EPChi2 = new ROOT::Fit::Chi2Function(data, *fitFunction);
111  ROOT::Fit::Fitter *fitter = new ROOT::Fit::Fitter();
112  fitter->Config().MinimizerOptions().SetMinimizerType("GSLMultiFit");
113  double params[] = {static_cast<double>(maxheight - pedestal), 0, static_cast<double>(pedestal)};
114  fitter->Config().SetParamsSettings(3, params);
115  fitter->Config().ParSettings(1).SetLimits(-1*m_peakTimeTemp, size1-m_peakTimeTemp);// set lim on time par
116  fitter->FitFCN(*EPChi2, nullptr, data.Size(), true);
117  ROOT::Fit::FitResult fitres = fitter->Result();
118  double chi2min = fitres.MinFcnValue();
119  chi2min /= size1-3; // divide by the number of dof
120  for (int i = 0; i < 3; i++)
121  {
122  v.push_back(f->GetParameter(i));
123  }
124 
125  v.push_back(chi2min);
126  h->Delete();
127  f->Delete();
128  delete fitFunction;
129  delete fitter;
130  delete EPChi2;
131  }
132  }
133  };
134 
135  t->Foreach(func, chnlvector);
136  int size3 = chnlvector.size();
137  std::vector<std::vector<float>> fit_params;
138  std::vector<float> fit_params_tmp;
139  for (int i = 0; i < size3; i++)
140  {
141  std::vector<float> tv = chnlvector.at(i);
142  int size2 = tv.size();
143  for (int q = 4; q > 0; q--)
144  {
145  fit_params_tmp.push_back(tv.at(size2 - q));
146  }
147  fit_params.push_back(fit_params_tmp);
148  fit_params_tmp.clear();
149  }
150  chnlvector.clear();
151  return fit_params;
152 }
153 
154 void CaloWaveformFitting::FastMax(float x0, float x1, float x2, float y0, float y1, float y2, float &xmax, float &ymax)
155 {
156  int n = 3;
157  double xp[3] = {x0, x1, x2};
158  double yp[3] = {y0, y1, y2};
159  TSpline3 *sp = new TSpline3("", xp, yp, n, "b2e2", 0, 0);
160  double X, Y, B, C, D;
161  ymax = y1;
162  xmax = x1;
163  if (y0 > ymax)
164  {
165  ymax = y0;
166  xmax = x0;
167  }
168  if (y2 > ymax)
169  {
170  ymax = y2;
171  xmax = x2;
172  }
173  for (int i = 0; i <= 1; i++)
174  {
175  sp->GetCoeff(i, X, Y, B, C, D);
176  if (D == 0)
177  {
178  if (C < 0)
179  {
180  // TSpline is a quadratic equation
181 
182  float root = -B / (2 * C) + X;
183  if (root >= xp[i] && root <= xp[i + 1])
184  {
185  float yvalue = sp->Eval(root);
186  if (yvalue > ymax)
187  {
188  ymax = yvalue;
189  xmax = root;
190  }
191  }
192  }
193  }
194  else
195  {
196  // find x when derivative = 0
197  float root = (-2 * C + sqrt(4 * C * C - 12 * B * D)) / (6 * D) + X;
198  if (root >= xp[i] && root <= xp[i + 1])
199  {
200  float yvalue = sp->Eval(root);
201  if (yvalue > ymax)
202  {
203  ymax = yvalue;
204  xmax = root;
205  }
206  }
207  root = (-2 * C - sqrt(4 * C * C - 12 * B * D)) / (6 * D) + X;
208  if (root >= xp[i] && root <= xp[i + 1])
209  {
210  float yvalue = sp->Eval(root);
211  if (yvalue > ymax)
212  {
213  ymax = yvalue;
214  xmax = root;
215  }
216  }
217  }
218  }
219  delete sp;
220  return;
221 }
222 std::vector<std::vector<float>> CaloWaveformFitting::calo_processing_fast(std::vector<std::vector<float>> chnlvector)
223 {
224  std::vector<std::vector<float>> fit_values;
225  int nchnls = chnlvector.size();
226  for (int m = 0; m < nchnls; m++)
227  {
228  std::vector<float> v = chnlvector.at(m);
229  int nsamples = v.size();
230 
231  double maxy = v.at(0);
232  float amp = 0;
233  float time = 0;
234  float ped = 0;
235  if (nsamples >= 3)
236  {
237  int maxx = 0;
238  for (int i = 0; i < nsamples; i++)
239  {
240  if (i < 3)
241  {
242  ped += v.at(i);
243  }
244  if (v.at(i) > maxy)
245  {
246  maxy = v.at(i);
247  maxx = i;
248  }
249  }
250  ped /= 3;
251  if (maxx == 0 || maxx == nsamples - 1)
252  {
253  amp = maxy;
254  time = maxx;
255  }
256  else
257  {
258  FastMax(maxx - 1, maxx, maxx + 1, v.at(maxx - 1), v.at(maxx), v.at(maxx + 1), time, amp);
259  }
260  }
261  amp -= ped;
262  std::vector<float> val = {amp, time, ped, 0};
263  fit_values.push_back(val);
264  val.clear();
265  }
266  return fit_values;
267 }