Belle II Software development
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
16using namespace Belle2;
17using namespace Belle2::ECL;
18using namespace std;
19
20double 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
32double 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
44void 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
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
136void 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 };
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.
STL namespace.
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