11 #include <ecl/utility/ECLDspEmulator.h>
13 #include <framework/logging/Logger.h>
22 T setInRange(T val, T min, T max)
24 if (val < min)
return min;
25 if (val > max)
return max;
30 namespace ShapeFitter {
31 bool amplitudeOverflow(
long long amp)
35 static const long long max_amp = 0x3FFFF - 128;
49 template <
typename INT>
50 ECLShapeFit lftda_(
const INT* f,
const INT* f1,
const INT* fg41,
51 const INT* fg43,
const INT* fg31,
const INT* fg32,
52 const INT* fg33,
int* y,
int ttrig2,
int la_thr,
53 int hit_thr,
int skip_thr,
int k_a,
int k_b,
54 int k_c,
int k_16,
int k1_chi,
int k2_chi,
55 int chi_thres,
bool adjusted_timing)
87 using namespace ShapeFitter;
98 const static long long int k_np[16] = {
118 const int ttrig = ttrig2 > 0 ? ttrig2 / 6 : 0;
122 if (k_16 + n_16 != 16) {
123 B2ERROR(
"Disagreement in the number of points: "
124 << k_16 <<
" and " << n_16);
129 if (!adjusted_timing) {
130 it0 = 48 + ((23 - ttrig) << 2);
132 it0 = 48 + ((143 - ttrig2) << 2) / 6;
135 int it_l = 0, it_h = 191;
137 int it = setInRange(it0, it_l, it_h);
149 int validity_code = c_GoodQuality;
150 bool skip_fit =
false;
152 bool skip_thr_flag =
false;
158 for (
int i = k_16; i < 16; i++)
162 const long long z0 = z00 >> kz_s;
166 result.fit.resize(31);
172 validity_code = c_InternalError;
181 A2 = fg41[ttrig * 16] * z0;
183 for (
int i = 1; i < 16; i++)
184 A2 += y[15 + i] * (
long long)fg41[ttrig * 16 + i];
186 A2 += (1 << (k_a - 1));
191 if (amplitudeOverflow(A2)) {
193 if (amplitudeOverflow(A1)) A1 >>= 3;
195 B2DEBUG(15, A1 <<
" 2");
197 validity_code = c_InternalError;
204 bool low_ampl =
false;
205 if (A2 < la_thr) low_ampl =
true;
215 if (!skip_fit && !low_ampl) {
216 for (
int iter = 1; iter <= 3; iter++) {
221 A1 = fg31[it * 16] * z0;
222 B1 = fg32[it * 16] * z0;
224 for (
int i = 1; i < 16; i++) {
225 A1 += fg31[it * 16 + i] * (
long long)y[15 + i];
226 B1 += fg32[it * 16 + i] * (
long long)y[15 + i];
228 A1 += (1 << (k_a - 1));
236 validity_code = c_LowAmp;
239 validity_code = c_InternalError;
248 if (amplitudeOverflow(A1)) {
250 if (amplitudeOverflow(A1)) A1 >>= 3;
252 B2DEBUG(15, A1 <<
" 1");
254 validity_code = c_InternalError;
272 skip_thr_flag =
true;
281 B2 = B1 >> (k_b - 13);
283 B2 = B1 << (13 - k_b);
288 int it_uncut = (B3 + 16) >> 5;
289 int delta_it = it_uncut - 256;
290 delta_it = setInRange(delta_it, -191, 191);
295 it = setInRange(it, it_l, it_h);
302 else if ((B3 >> 1) <= 0x400)
305 delta_T = ((B3 * 3 + 4) >> 3) - 3072;
307 int t_uncut = it_current * 12 + delta_T;
308 t_uncut = setInRange(t_uncut, -4096, 4095);
311 if (!adjusted_timing) {
312 T += ((210 - ttrig2) << 3);
314 T += ((215 - ttrig2) << 3) - 4;
317 T = setInRange(T, -2048, 2047);
321 C1 = fg33[it * 16] * z0;
322 for (
int i = 1; i < 16; i++)
323 C1 += fg33[it * 16 + i] * (
long long)y[15 + i];
324 C1 += (1 << (k_c - 1));
332 if (!skip_fit && low_ampl) {
336 validity_code = c_InternalError;
339 validity_code = c_LowAmp;
344 C1 = fg43[ttrig * 16] * z0;
345 for (
int i = 1; i < 16; i++)
346 C1 += fg43[ttrig * 16 + i] * (
long long)y[15 + i];
347 C1 += (1 << (k_c - 1));
353 long long chi_sq = 0;
358 int B1_chi = B1 >> k_b;
361 result.fit[0] = A1 * f[it * 16] + B1_chi * f1[it * 16];
362 result.fit[0] >>= k1_chi;
364 for (
int i = 1; i <= 15; i++) {
365 result.fit[i] = result.fit[0];
368 for (
int i = 1; i < 16; i++) {
369 result.fit[i + 15] = A1 * f[it * 16 + i] + B1_chi * f1[it * 16 + i];
370 result.fit[i + 15] >>= k1_chi;
371 result.fit[i + 15] += C1;
377 chi_thr = (A1 >> 1) * (A1 >> 1);
378 chi_thr >>= (k2_chi - 2);
379 chi_thr += chi_thres;
385 chi = n_16 * result.fit[0] - z00;
388 chi_sq *= k_np[n_16 - 1];
390 for (
int i = 1; i < 16; i++) {
391 chi = result.fit[i + 15] - y[i + 15];
395 if (chi_sq > chi_thr && validity_code != c_LowAmp) validity_code = c_BadChi2;
396 if (C1 < 0 && validity_code == c_GoodQuality) validity_code = c_BadChi2;
404 int hit_val = y[20] + y[21] - (y[12] + y[13] + y[14] + y[15]) / 2;
405 if (hit_val <= hit_thr) {
412 if (A1 < skip_thr && validity_code != c_InternalError) {
413 skip_thr_flag =
true;
420 result.quality = validity_code % 4;
421 result.hit_thr = validity_code / 4;
422 result.skip_thr = skip_thr_flag;
423 result.low_amp = low_ampl;
424 result.pedestal = result.fit[0];
426 result.chi2 = chi_sq;
431 template ECLShapeFit lftda_<short>(
const short* f,
const short* f1,
const short* fg41,
432 const short* fg43,
const short* fg31,
const short* fg32,
433 const short* fg33,
int* y,
int ttrig2,
int la_thr,
434 int hit_thr,
int skip_thr,
int k_a,
int k_b,
435 int k_c,
int k_16,
int k1_chi,
int k2_chi,
436 int chi_thres,
bool adjusted_timing);
437 template ECLShapeFit lftda_<int>(
const int* f,
const int* f1,
const int* fg41,
438 const int* fg43,
const int* fg31,
const int* fg32,
439 const int* fg33,
int* y,
int ttrig2,
int la_thr,
440 int hit_thr,
int skip_thr,
int k_a,
int k_b,
441 int k_c,
int k_16,
int k1_chi,
int k2_chi,
442 int chi_thres,
bool adjusted_timing);