Belle II Software  release-08-01-10
ECLDspFitterPure.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 #include <ecl/digitization/ECLDspFitterPure.h>
9 #include <TVectorD.h>
10 #include <TMatrixD.h>
11 #include <TDecompLU.h>
12 #include <numeric>
13 #include <algorithm>
14 #include <iostream>
15 
16 using namespace Belle2;
17 using namespace Belle2::ECL;
18 using namespace std;
19 
20 double Belle2::ECL::func(int i, int ifine,
22 {
23  if (i == 0) return 0;
24  if (ifine < 0) {
25  i--;
26  if (i == 0) return 0;
27  ifine = EclConfigurationPure::m_ndtPure + ifine;
28  }
29  return signal.m_ft[(i - 1) * EclConfigurationPure::m_ndtPure + ifine ];
30 }
31 
32 double Belle2::ECL::func1(int i, int ifine,
34 {
35  if (i == 0) return 0;
36  if (ifine < 0) {
37  i--;
38  if (i == 0) return 0;
39  ifine = EclConfigurationPure::m_ndtPure + ifine;
40  }
41  return signal.m_ft1[(i - 1) * EclConfigurationPure::m_ndtPure + ifine ];
42 }
43 
44 void Belle2::ECL::initParams(EclConfigurationPure::fitparamspure_t& params,
46 {
47 
48  for (int i = 0; i < 16; i++) {
50  // cout << i << ":" << k << " " << func( i, k, signal) << " " << func1(i, k, signal) << endl;
51  if (k < 0) params.f[i][ EclConfigurationPure::m_ndtPure - 1 - k] = func(i, k, signal);
52  else params.f[i][k] = func(i, k, signal);
53  }
54  }
55 
56  double kdt = 0.001 / (EclConfigurationPure::getTickPure() / EclConfigurationPure::m_ndtPure) ; // df / dtau = df / dt * dt / dtau
57 
58  params.c002 = 0;
59  for (int h = 0; h < 16; h++) {
60  params.c001[h] = 0;
61  for (int j = 0; j < 16; j++) {
62  params.c001[h] -= params.invC[h][j];
63  params.c002 += params.invC[h][j];
64  }
65  params.c001[h] *= 2;
66  }
67 
68  for (int k = 0; k < EclConfigurationPure::m_ndtPure; k++) {
69  params.c110[k] = 0;
70  params.c200[k] = 0;
71  params.c020[k] = 0;
72  params.c101[k] = 0;
73  params.c011[k] = 0;
74  for (int i = 0; i < 16; i++) {
75  for (int j = 0; j < 16; j++) {
76  params.c110[k] += kdt * func1(i, k, signal) * params.invC[i][j] * func(j, k, signal);
77  params.c200[k] += func(i, k, signal) * params.invC[i][j] * func(j, k, signal);
78  params.c020[k] += kdt * func1(i, k, signal) * params.invC[i][j] * func1(j, k, signal) * kdt;
79  params.c101[k] += func(i, k, signal) * params.invC[i][j];
80  params.c011[k] += kdt * func1(i, k, signal) * params.invC[i][j];
81  }
82  }
83  params.c110[k] *= 2;
84  params.c101[k] *= 2;
85  params.c011[k] *= 2;
86  }
87 
88  int off = EclConfigurationPure::m_ndtPure - 1;
89  for (int k = 1; k < EclConfigurationPure::m_ndtPure; k++) {
90  params.c110[k + off] = 0;
91  params.c200[k + off] = 0;
92  params.c020[k + off] = 0;
93  params.c101[k + off] = 0;
94  params.c011[k + off] = 0;
95  for (int i = 0; i < 16; i++) {
96  for (int j = 0; j < 16; j++) {
97  params.c110[k + off] += kdt * func1(i, -k, signal) * params.invC[i][j] * func(j, -k, signal);
98  params.c200[k + off] += func(i, -k, signal) * params.invC[i][j] * func(j, -k, signal);
99  params.c020[k + off] += kdt * func1(i, -k, signal) * params.invC[i][j] * func1(j, -k, signal) * kdt;
100  params.c101[k + off] += func(i, -k, signal) * params.invC[i][j];
101  params.c011[k + off] += kdt * func1(i, -k, signal) * params.invC[i][j];
102  }
103  }
104  params.c110[k + off] *= 2;
105  params.c101[k + off] *= 2;
106  params.c011[k + off] *= 2;
107  }
108 
109 
110  for (int h = 0; h < 16; h++) {
111 
112  for (int k = 0; k < EclConfigurationPure::m_ndtPure; k++) {
113  params.c100[h][k] = 0;
114  params.c010[h][k] = 0;
115  for (int i = 0; i < 16; i++) {
116  params.c100[h][k] -= func(i, k, signal) * params.invC[i][h];
117  params.c010[h][k] -= kdt * func1(i, k, signal) * params.invC[i][h];
118  }
119  params.c100[h][k] *= 2;
120  params.c010[h][k] *= 2;
121  }
122  for (int k = 1; k < EclConfigurationPure::m_ndtPure; k++) {
123  params.c100[h][k + off] = 0;
124  params.c010[h][k + off] = 0;
125  for (int i = 0; i < 16; i++) {
126  params.c100[h][k + off] -= func(i, -k, signal) * params.invC[i][h];
127  params.c010[h][k + off] -= kdt * func1(i, -k, signal) * params.invC[i][h];
128  }
129  params.c100[h][k + off] *= 2;
130  params.c010[h][k + off] *= 2;
131  }
132 
133  }
134 }
135 
136 void Belle2::ECL::DSPFitterPure(const EclConfigurationPure::fitparamspure_t& f, const int* FitA, const int ttrig, int& amp,
137  double& time, double& chi2, int& iter)
138 {
139  int baseline = accumulate(FitA, FitA + 16, 0) / 16;
140  const int* imax = max_element(FitA, FitA + EclConfigurationPure::m_nsmp);
141 
142  amp = *imax - baseline;
143  //time = imax - FitA;
144 
145 
146  int dt = ttrig;
147  double y[16];
148  y[0] = baseline;
149  for (int i = 16; i < EclConfigurationPure::m_nsmp; i++) y[i - 15] = FitA[i];
150 
151  //cout << "ttrig = " << dt << endl;
152  // for (int i=0; i<16; i++ ) cout << "y_" << i << " = " << y[i] << endl;
153 
154  double k100 { 0 }, k010{ 0 }, k001{ 0 };
155  int offset = EclConfigurationPure::m_ndtPure;
156  if (dt < 0) dt = offset - 1 - dt;
157  for (int i = 0; i < 16; i++) {
158  k100 += f.c100[i][dt] * y[i];
159  k010 += f.c010[i][dt] * y[i];
160  k001 += f.c001[i] * y[i];
161  }
162 
163  double a[] = { 2 * f.c200[dt], f.c110[dt], f.c101[dt],
164  f.c110[dt], 2 * f.c020[dt], f.c011[dt],
165  f.c101[dt], f.c011[dt], 2 * f.c002
166  };
167 
168  TMatrixD M1(3, 3);
169  M1.SetMatrixArray(a);
170 
171  TVectorD C(3);
172  C[0] = - k100;
173  C[1] = - k010;
174  C[2] = - k001;
175  /*
176  cout << "(" << -k100 << "==" << C[0] << ","
177  << "(" << -k010 << "==" << C[1] << ","
178  << "(" << -k001 << "==" << C[2] << ","
179  << endl;
180 
181  */
182  // C.Print();
183  TDecompLU solver(M1);
184  bool ok;
185  C = solver.Solve(C, ok);
186  /*
187  if ( !ok ) {
188  cout << "Fit failed" << endl;
189  cout << "dt = " << dt << endl;
190  M1.Print();
191  cout << "solution -->" << endl;
192  C.Print();
193  }
194  */
195  amp = C[0];
196 
197  /*
198  cout << "t0 = " << ttrig << endl;
199  cout << "P = " << C[2] << endl;
200  cout << "A = " << C[0] << endl;
201  cout << "B = A * t = " << C[1] << endl;
202  cout << "dt = B / A = " << C[1] / C[0] << endl;
203  */
204 
205  double A = C[0];
206  double B = C[1];
207  double P = C[2];
208 
209  /*
210  for (int i=1; i<16; i++)
211  cout << "A= " << C[0] << " f = " << f.f[i][dt] << " A*f = " << C[0]*f.f[i][dt] << " y = " << y[i] << endl;
212  */
213 
214  chi2 = f.c200[dt] * A * A + f.c020[dt] * B * B + f.c002 * P * P +
215  f.c110[dt] * A * B + f.c101[dt] * A * P + f.c011[dt] * B * P +
216  k100 * A + k010 * B + k001 * P ;
217  for (int i = 0; i < 16; i++)
218  for (int j = 0; j < 16; j++)
219  chi2 += y[i] * f.invC[i][j] * y[j];
220 
221  // cout << "chi2 = " << chi2 << endl;
222  double deltaT = C[1] / C[0] ;
223  int intTime = ttrig + round(deltaT) ;
224  // time = -ttrig - C[1] / C[0] ;
225  time = -(ttrig + deltaT);
226  // cout << "time : " << time << endl;
227  bool intime = abs(intTime) < EclConfigurationPure::m_ndtPure - 1;
228  if (iter < 3 && intime) {
229  iter++;
230  DSPFitterPure(f, FitA, intTime, amp, time, chi2, iter);
231  }
232 
233  if (intime && abs(deltaT) > 0.5 && iter++ < 10)
234  DSPFitterPure(f, FitA, intTime, amp, time, chi2, iter);
235 }
static double getTickPure()
Getter for m_tickPure.
static constexpr int m_ndtPure
number of points per ADC tick where signal fit procedure parameters are evaluated
static constexpr int m_nsmp
number of ADC measurements for signal fitting
Abstract base class for different kinds of events.
A struct for the fit parameters for a single channel of the pure CsI calorimeter (in the simulation,...
a struct for a signal sample for the pure CsI calorimeter