9#include <ecl/utility/ECLDspEmulator.h>
11#include <framework/logging/Logger.h>
20 T setInRange(T val, T min, T max)
22 if (val < min)
return min;
23 if (val > max)
return max;
28 namespace ShapeFitter {
29 bool amplitudeOverflow(
long long amp)
33 static const long long max_amp = 0x3FFFF - 128;
47 template <
typename INT>
48 ECLShapeFit lftda_(
const INT* f,
const INT* f1,
const INT* fg41,
49 const INT* fg43,
const INT* fg31,
const INT* fg32,
50 const INT* fg33,
int* y,
int ttrig2,
int la_thr,
51 int hit_thr,
int skip_thr,
int k_a,
int k_b,
52 int k_c,
int k_16,
int k1_chi,
int k2_chi,
53 int chi_thres,
bool adjusted_timing)
85 using namespace ShapeFitter;
96 const static long long int k_np[16] = {
116 const int ttrig = ttrig2 > 0 ? ttrig2 / 6 : 0;
120 if (k_16 + n_16 != 16) {
121 B2ERROR(
"Disagreement in the number of points: "
122 << k_16 <<
" and " << n_16);
127 if (!adjusted_timing) {
128 it0 = 48 + ((23 - ttrig) << 2);
130 it0 = 48 + ((143 - ttrig2) << 2) / 6;
133 int it_l = 0, it_h = 191;
135 int it = setInRange(it0, it_l, it_h);
147 int validity_code = c_GoodQuality;
148 bool skip_fit =
false;
150 bool skip_thr_flag =
false;
156 for (
int i = k_16; i < 16; i++)
160 const long long z0 = z00 >> kz_s;
164 result.fit.resize(31);
170 validity_code = c_InternalError;
179 A2 = fg41[ttrig * 16] * z0;
181 for (
int i = 1; i < 16; i++)
182 A2 += y[15 + i] * (
long long)fg41[ttrig * 16 + i];
184 A2 += (1 << (k_a - 1));
189 if (amplitudeOverflow(A2)) {
191 if (amplitudeOverflow(A1)) A1 >>= 3;
193 B2DEBUG(15, A1 <<
" 2");
195 validity_code = c_InternalError;
202 bool low_ampl =
false;
203 if (A2 < la_thr) low_ampl =
true;
213 if (!skip_fit && !low_ampl) {
214 for (
int iter = 1; iter <= 3; iter++) {
219 A1 = fg31[it * 16] * z0;
220 B1 = fg32[it * 16] * z0;
222 for (
int i = 1; i < 16; i++) {
223 A1 += fg31[it * 16 + i] * (
long long)y[15 + i];
224 B1 += fg32[it * 16 + i] * (
long long)y[15 + i];
226 A1 += (1 << (k_a - 1));
234 validity_code = c_LowAmp;
237 validity_code = c_InternalError;
246 if (amplitudeOverflow(A1)) {
248 if (amplitudeOverflow(A1)) A1 >>= 3;
250 B2DEBUG(15, A1 <<
" 1");
252 validity_code = c_InternalError;
270 skip_thr_flag =
true;
279 B2 = B1 >> (k_b - 13);
281 B2 = B1 << (13 - k_b);
286 int it_uncut = (B3 + 16) >> 5;
287 int delta_it = it_uncut - 256;
288 delta_it = setInRange(delta_it, -191, 191);
293 it = setInRange(it, it_l, it_h);
300 else if ((B3 >> 1) <= 0x400)
303 delta_T = ((B3 * 3 + 4) >> 3) - 3072;
305 int t_uncut = it_current * 12 + delta_T;
306 t_uncut = setInRange(t_uncut, -4096, 4095);
309 if (!adjusted_timing) {
310 T += ((210 - ttrig2) << 3);
312 T += ((215 - ttrig2) << 3) - 4;
315 T = setInRange(T, -2048, 2047);
319 C1 = fg33[it * 16] * z0;
320 for (
int i = 1; i < 16; i++)
321 C1 += fg33[it * 16 + i] * (
long long)y[15 + i];
322 C1 += (1 << (k_c - 1));
330 if (!skip_fit && low_ampl) {
334 validity_code = c_InternalError;
337 validity_code = c_LowAmp;
342 C1 = fg43[ttrig * 16] * z0;
343 for (
int i = 1; i < 16; i++)
344 C1 += fg43[ttrig * 16 + i] * (
long long)y[15 + i];
345 C1 += (1 << (k_c - 1));
351 long long chi_sq = 0;
356 int B1_chi = B1 >> k_b;
359 result.fit[0] = A1 * f[it * 16] + B1_chi * f1[it * 16];
360 result.fit[0] >>= k1_chi;
362 for (
int i = 1; i <= 15; i++) {
363 result.fit[i] = result.fit[0];
366 for (
int i = 1; i < 16; i++) {
367 result.fit[i + 15] = A1 * f[it * 16 + i] + B1_chi * f1[it * 16 + i];
368 result.fit[i + 15] >>= k1_chi;
369 result.fit[i + 15] += C1;
375 chi_thr = (A1 >> 1) * (A1 >> 1);
376 chi_thr >>= (k2_chi - 2);
377 chi_thr += chi_thres;
383 chi = n_16 * result.fit[0] - z00;
386 chi_sq *= k_np[n_16 - 1];
388 for (
int i = 1; i < 16; i++) {
389 chi = result.fit[i + 15] - y[i + 15];
393 if (chi_sq > chi_thr && validity_code != c_LowAmp) validity_code = c_BadChi2;
394 if (C1 < 0 && validity_code == c_GoodQuality) validity_code = c_BadChi2;
402 int hit_val = y[20] + y[21] - (y[12] + y[13] + y[14] + y[15]) / 2;
403 if (hit_val <= hit_thr) {
410 if (A1 < skip_thr && validity_code != c_InternalError) {
411 skip_thr_flag =
true;
418 result.quality = validity_code % 4;
419 result.hit_thr = validity_code / 4;
420 result.skip_thr = skip_thr_flag;
421 result.low_amp = low_ampl;
422 result.pedestal = result.fit[0];
424 result.chi2 = chi_sq;
429 template ECLShapeFit lftda_<short>(
const short* f,
const short* f1,
const short* fg41,
430 const short* fg43,
const short* fg31,
const short* fg32,
431 const short* fg33,
int* y,
int ttrig2,
int la_thr,
432 int hit_thr,
int skip_thr,
int k_a,
int k_b,
433 int k_c,
int k_16,
int k1_chi,
int k2_chi,
434 int chi_thres,
bool adjusted_timing);
435 template ECLShapeFit lftda_<int>(
const int* f,
const int* f1,
const int* fg41,
436 const int* fg43,
const int* fg31,
const int* fg32,
437 const int* fg33,
int* y,
int ttrig2,
int la_thr,
438 int hit_thr,
int skip_thr,
int k_a,
int k_b,
439 int k_c,
int k_16,
int k1_chi,
int k2_chi,
440 int chi_thres,
bool adjusted_timing);
Abstract base class for different kinds of events.