BmnRoot
Loading...
Searching...
No Matches
PronyFitter.cxx
Go to the documentation of this file.
1/* Copyright (C) 2020-2021 Institute for Nuclear Research, Moscow
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Nikolay Karpushkin [committer] */
4
5#include "PronyFitter.h"
6
8#include "PolynomRealRoots.h"
9#include "MatrixInversion.h"
10
11#include <limits>
12
14
15PronyFitter::PronyFitter(int model_order, int exponent_number, int gate_beg,
16 int gate_end) {
17 Initialize(model_order, exponent_number, gate_beg, gate_end);
18}
19
20void PronyFitter::Initialize(int model_order, int exponent_number, int gate_beg,
21 int gate_end) {
22 fModelOrder = model_order;
23 fExpNumber = exponent_number;
24 fGateBeg = gate_beg;
25 fGateEnd = gate_end;
26 AllocData();
27}
28
29void PronyFitter::AllocData() {
30 fz = new std::complex<float>[fExpNumber + 1];
31 fh = new std::complex<float>[fExpNumber + 1];
32 for (int i = 0; i < fExpNumber + 1; i++) {
33 fz[i] = {0., 0.};
34 fh[i] = {0., 0.};
35 }
36}
37
38void PronyFitter::SetWaveform(std::vector<float> &Wfm,
39 float ZeroLevel) {
40 fWfm.assign(Wfm.begin(), Wfm.end());
41 fZeroLevel = ZeroLevel;
42 fSampleTotal = fWfm.size();
43 fFitWfm.clear();
44 fFitWfm.resize(fSampleTotal);
45}
46
47float PronyFitter::GoToLevel(float Level, int *point, int iterator,
48 int iLastPoint) {
49 float ResultTime;
50 while ((*point > 0) && (*point < iLastPoint)) {
51
52 if ((Level - fWfm.at(*point)) * (Level - fWfm.at(*point + iterator)) <= 0) {
53 ResultTime = LevelBy2Points((float)(*point), fWfm.at(*point),
54 (float)(*point + iterator),
55 fWfm.at(*point + iterator), Level);
56 return ResultTime;
57 }
58 *point += iterator;
59 } // while
60
61 *point = -1;
62 return 0;
63}
64
66 auto const max_iter = std::max_element(fWfm.begin() + fGateBeg, fWfm.begin() + fGateEnd);
67 int Amplitude = (int) *max_iter - fZeroLevel;
68 int timeMax = (int) std::distance(fWfm.begin(), max_iter);
69
70 float trsh_03 = fZeroLevel + Amplitude * 0.3;
71 float trsh_09 = fZeroLevel + Amplitude * 0.9;
72
73 int point = timeMax;
74 float front_time_beg_03 = GoToLevel(trsh_03, &point, -1, fSampleTotal);
75
76 point = timeMax;
77 float front_time_end = GoToLevel(trsh_09, &point, -1, fSampleTotal);
78
79 return CalcSignalBegin(front_time_beg_03, front_time_end);
80}
81
82int PronyFitter::CalcSignalBegin(float front_time_beg_03,
83 float front_time_end) {
84 return std::ceil((3 * front_time_beg_03 - front_time_end) / 2.);
85}
86
87void PronyFitter::SetSignalBegin(int SignalBeg) {
88 fSignalBegin = SignalBeg;
89 if (fIsDebug)
90 printf("\nsignal begin %i zero level %f\n", fSignalBegin, fZeroLevel);
91}
92
94 float rho_f = 999;
95 float rho_b = 999;
96 std::vector<float> a_f;
97 std::vector<float> a_b;
98
99 CovarianceDirect(rho_f, a_f, rho_b, a_b);
100 // CovarianceQRmod(rho_f, a_f, rho_b, a_b);
101
102 if (fIsDebug) {
103 printf("LSerr %e, SLE roots forward ", rho_f);
104 for (uint16_t i = 0; i < a_f.size(); i++)
105 printf(" %e ", a_f.at(i));
106 printf("\n");
107 printf("LSerr %e, SLE roots backward ", rho_b);
108 for (uint16_t i = 0; i < a_b.size(); i++)
109 printf(" %e ", a_b.at(i));
110 printf("\n");
111 }
112
113 float *a_arr = new float[fModelOrder + 1];
114 for (int i = 0; i < fModelOrder + 1; i++)
115 a_arr[i] = 0.;
116
117 // for(uint16_t i = 0; i < a_f.size(); i++) a_arr[i+1] = 0.5*(a_f.at(i) +
118 // a_b.at(i));
119 for (uint16_t i = 0; i < a_f.size(); i++)
120 a_arr[i + 1] = a_f.at(i);
121 a_arr[0] = 1.;
122
123 float *zr = new float[fModelOrder];
124 float *zi = new float[fModelOrder];
125 for (int i = 0; i < fModelOrder; i++) {
126 zr[i] = 0.;
127 zi[i] = 0.;
128 }
129
130 int total_roots;
131 if(fModelOrder % 2 == 0) polynomComplexRoots(zr, zi, fModelOrder, a_arr, total_roots);
132 else polynomRealRoots(zr, fModelOrder, a_arr, total_roots);
133
134 if (fIsDebug) {
135 printf("forward polinom roots ");
136 for (int i = 0; i < fModelOrder; i++)
137 printf("%.5f%+.5fi ", zr[i], zi[i]);
138 printf("\n");
139
140 printf("forward freqs ");
141 for (int i = 0; i < fModelOrder; i++)
142 printf("%.5f ", log(zr[i]));
143 printf("\n");
144 }
145
146 std::complex<float> *z_arr = new std::complex<float>[fExpNumber + 1];
147 for (int i = 0; i < fExpNumber; i++) {
148 if (std::isfinite(zr[i]))
149 z_arr[i + 1] = {zr[i], zi[i]};
150 else
151 z_arr[i + 1] = 0.;
152 }
153 z_arr[0] = {1., 0.};
154 SetHarmonics(z_arr);
155 fTotalPolRoots = total_roots;
156
157 delete[] a_arr;
158 delete[] zr;
159 delete[] zi;
160 delete[] z_arr;
161}
162
163void PronyFitter::CovarianceDirect(float & /*rho_f*/, std::vector<float> &a_f,
164 float & /*rho_b*/,
165 std::vector<float> & /*a_b*/) {
166 std::vector<float> kWfmSignal;
167 // filtering constant fraction
168 for (int sample_curr = fSignalBegin; sample_curr <= fGateEnd; sample_curr++)
169 kWfmSignal.push_back(fWfm.at(sample_curr) - fZeroLevel);
170 int n = kWfmSignal.size();
171
172 float **Rkm_arr = new float *[fModelOrder];
173 for (int i = 0; i < fModelOrder; i++) {
174 Rkm_arr[i] = new float[fModelOrder];
175 for (int j = 0; j < fModelOrder; j++)
176 Rkm_arr[i][j] = 0.;
177 }
178
179 float *R0k_arr = new float[fModelOrder];
180 for (int i = 0; i < fModelOrder; i++)
181 R0k_arr[i] = 0.;
182
183 // Regression via linear prediction forward
184 for (int i = 1; i <= fModelOrder; i++)
185 for (int j = 1; j <= fModelOrder; j++)
186 for (int sample_curr = fModelOrder; sample_curr < n; sample_curr++)
187 Rkm_arr[i - 1][j - 1] += (float)(kWfmSignal.at(sample_curr - i) *
188 kWfmSignal.at(sample_curr - j));
189
190 for (int i = 1; i <= fModelOrder; i++)
191 for (int sample_curr = fModelOrder; sample_curr < n; sample_curr++)
192 R0k_arr[i - 1] -= (float)(kWfmSignal.at(sample_curr) *
193 kWfmSignal.at(sample_curr - i));
194
195 if (fIsDebug) {
196 printf("system forward\n");
197 for (int i = 0; i < fModelOrder; i++) {
198 for (int j = 0; j < fModelOrder; j++)
199 printf("%e ", Rkm_arr[i][j]);
200 printf("%e\n", R0k_arr[i]);
201 }
202 }
203
204 float *a = new float[fModelOrder];
205 for (int i = 0; i < fModelOrder; i++)
206 a[i] = 0.;
207
208 SolveSLEGauss(a, Rkm_arr, R0k_arr, fModelOrder);
209 // SolveSLECholesky(a, Rkm_arr, R0k_arr, fModelOrder);
210 if (fIsDebug) {
211 printf("SLE roots ");
212 for (int i = 0; i < fModelOrder; i++)
213 printf(" %e ", a[i]);
214 printf("\n");
215 }
216
217 a_f.resize(fModelOrder);
218 for (int i = 0; i < fModelOrder; i++)
219 a_f.at(i) = a[i];
220
221 for (int i = 0; i < fModelOrder; i++)
222 delete[] Rkm_arr[i];
223 delete[] Rkm_arr;
224 delete[] R0k_arr;
225 delete[] a;
226}
227
228void PronyFitter::CovarianceQRmod(float &rho_f, std::vector<float> &a_f,
229 float &rho_b, std::vector<float> &a_b) {
230
231 /*
232% Copyright (c) 2019 by S. Lawrence Marple Jr.
233%
234%
235p
236--
237order of linear prediction/autoregressive filter
238%
239x
240--
241vector of data samples
242%
243rho_f
244--
245least squares estimate of forward linear prediction variance
246%
247a_f
248--
249vector of forward linear prediction/autoregressive
250parameters
251%
252rho_b
253--
254least squares estimate of backward linear prediction
255variance
256%
257a_b
258--
259vector of backward linear prediction/autoregressive
260parameters
261
262*/
263
264 //******** Initialization ********
265
266 std::vector<float> kWfmSignal;
267 // filtering constant fraction
268 for (int sample_curr = fSignalBegin; sample_curr <= fGateEnd; sample_curr++)
269 kWfmSignal.push_back(fWfm.at(sample_curr) - fZeroLevel);
270 int n = kWfmSignal.size();
271 if (2 * fModelOrder + 1 > n) {
272 if (fIsDebug)
273 printf("ERROR: Order too high; will make solution singular\n");
274 return;
275 }
276
277 float r1 = 0.;
278 for (int k = 1; k <= n - 2; k++)
279 r1 += std::pow(kWfmSignal.at(k), 2);
280
281 float r2 = std::pow(kWfmSignal.front(), 2);
282 float r3 = std::pow(kWfmSignal.back(), 2);
283
284 rho_f = r1 + r3;
285 rho_b = r1 + r2;
286 r1 = 1. / (rho_b + r3);
287
288 std::vector<float> c, d;
289 c.push_back(kWfmSignal.back() * r1);
290 d.push_back(kWfmSignal.front() * r1);
291
292 float gam = 0.;
293 float del = 0.;
294 std::vector<float> ef, eb, ec, ed;
295 std::vector<float> coeffs;
296 coeffs.resize(6);
297
298 for (int v_iter = 0; v_iter < n; v_iter++) {
299 ef.push_back(kWfmSignal.at(v_iter));
300 eb.push_back(kWfmSignal.at(v_iter));
301 ec.push_back(c.at(0) * kWfmSignal.at(v_iter));
302 ed.push_back(d.at(0) * kWfmSignal.at(v_iter));
303 }
304
305 //******** Main Recursion ********
306
307 for (int k = 1; k <= fModelOrder; k++) {
308 if (rho_f <= 0 || rho_b <= 0) {
309 if (fIsDebug)
310 printf("PsdPronyFitter::ERROR: prediction squared error was less "
311 "than or equal to zero\n");
312 return;
313 }
314
315 gam = 1. - ec.at(n - k);
316 del = 1. - ed.front();
317 if (gam <= 0 || gam > 1 || del <= 0 || del > 1) {
318 if (fIsDebug)
319 printf("PsdPronyFitter::ERROR: GAM or DEL gain factor not in "
320 "expected range 0 to 1\n");
321 return;
322 }
323
324 // computation for k-th order reflection coefficients
325 std::vector<float> eff, ebb;
326 eff.resize(n);
327 ebb.resize(n);
328 float delta = 0.;
329 for (int v_iter = 0; v_iter < n - 1; v_iter++) {
330 eff.at(v_iter) = ef.at(v_iter + 1);
331 ebb.at(v_iter) = eb.at(v_iter);
332 delta += eff.at(v_iter) * ebb.at(v_iter);
333 }
334
335 float k_f = -delta / rho_b;
336 float k_b = -delta / rho_f;
337
338 //% order updates for squared prediction errors rho_f and rho_b
339 rho_f = rho_f * (1 - k_f * k_b);
340 rho_b = rho_b * (1 - k_f * k_b);
341
342 //% order updates for linear prediction parameter arrays a_f and a_b
343 std::vector<float> temp_af = a_f;
344 std::reverse(std::begin(a_b), std::end(a_b));
345 for (uint16_t i = 0; i < a_f.size(); i++)
346 a_f.at(i) += k_f * a_b.at(i);
347 a_f.push_back(k_f);
348
349 std::reverse(std::begin(a_b), std::end(a_b));
350 std::reverse(std::begin(temp_af), std::end(temp_af));
351 for (uint16_t i = 0; i < a_b.size(); i++)
352 a_b.at(i) += k_b * temp_af.at(i);
353 a_b.push_back(k_b);
354
355 //% check if maximum order has been reached
356 if (k == fModelOrder) {
357 rho_f = rho_f / (n - fModelOrder);
358 rho_b = rho_b / (n - fModelOrder);
359 return;
360 }
361
362 //% order updates for prediction error arrays ef and eb
363 for (int v_iter = 0; v_iter < n; v_iter++) {
364 eb.at(v_iter) = ebb.at(v_iter) + k_b * eff.at(v_iter);
365 ef.at(v_iter) = eff.at(v_iter) + k_f * ebb.at(v_iter);
366 }
367
368 //% coefficients for next set of updates
369 coeffs.at(0) = ec.front();
370 coeffs.at(1) = coeffs.at(0) / del;
371 coeffs.at(2) = coeffs.at(0) / gam;
372
373 //% time updates for gain arrays c' and d"
374 std::vector<float> temp_c = c;
375 for (uint16_t v_iter = 0; v_iter < c.size(); v_iter++) {
376 c.at(v_iter) += coeffs.at(1) * d.at(v_iter);
377 d.at(v_iter) += coeffs.at(2) * temp_c.at(v_iter);
378 }
379
380 //% time updates for ec' and ed"
381 std::vector<float> temp_ec = ec;
382 for (int v_iter = 0; v_iter < n; v_iter++) {
383 ec.at(v_iter) += coeffs.at(1) * ed.at(v_iter);
384 ed.at(v_iter) += coeffs.at(2) * temp_ec.at(v_iter);
385 }
386
387 std::vector<float> ecc, edd;
388 ecc.resize(n);
389 edd.resize(n);
390 for (int v_iter = 0; v_iter < n - 1; v_iter++) {
391 ecc.at(v_iter) = ec.at(v_iter + 1);
392 edd.at(v_iter) = ed.at(v_iter);
393 }
394
395 if (rho_f <= 0 || rho_b <= 0) {
396 if (fIsDebug)
397 printf("PsdPronyFitter::ERROR2: prediction squared error was less "
398 "than or equal to zero\n");
399 return;
400 }
401 gam = 1 - ecc.at(n - k - 1); // n-k?
402 del = 1 - edd.front();
403 if (gam <= 0 || gam > 1 || del <= 0 || del > 1) {
404 if (fIsDebug)
405 printf("PsdPronyFitter::ERROR2: GAM or DEL gain factor not in "
406 "expected range 0 to 1\n");
407 return;
408 }
409
410 //% coefficients for next set of updates
411 coeffs.at(0) = ef.front();
412 coeffs.at(1) = eb.at(n - k - 1); // n-k?
413 coeffs.at(2) = coeffs.at(1) / rho_b;
414 coeffs.at(3) = coeffs.at(0) / rho_f;
415 coeffs.at(4) = coeffs.at(0) / del;
416 coeffs.at(5) = coeffs.at(1) / gam;
417
418 //% order updates for c and d; time updates for a_f' and a_b"
419 std::vector<float> temp_ab = a_b;
420 std::reverse(std::begin(temp_ab), std::end(temp_ab));
421 std::reverse(std::begin(c), std::end(c));
422
423 for (uint16_t i = 0; i < a_b.size(); i++)
424 a_b.at(i) += coeffs.at(5) * c.at(i);
425 std::reverse(std::begin(c), std::end(c));
426
427 for (uint16_t i = 0; i < c.size(); i++)
428 c.at(i) += coeffs.at(2) * temp_ab.at(i);
429 c.push_back(coeffs.at(2));
430
431 std::vector<float> temp_af2 = a_f;
432 for (uint16_t i = 0; i < a_f.size(); i++)
433 a_f.at(i) += coeffs.at(4) * d.at(i);
434
435 for (uint16_t i = 0; i < d.size(); i++)
436 d.at(i) += coeffs.at(3) * temp_af2.at(i);
437 d.insert(d.begin(), coeffs.at(3));
438
439 //% time updates for rho_f' and rho_b"
440 rho_f = rho_f - coeffs.at(4) * coeffs.at(0);
441 rho_b = rho_b - coeffs.at(5) * coeffs.at(1);
442
443 if (rho_f <= 0 || rho_b <= 0) {
444 if (fIsDebug)
445 printf("PsdPronyFitter::ERROR3: prediction squared error was less "
446 "than or equal to zero\n");
447 return;
448 }
449
450 //% order updates for ec and ed; time updates for ef' and eb"
451 for (int v_iter = 0; v_iter < n; v_iter++) {
452 ec.at(v_iter) = ecc.at(v_iter) + coeffs.at(2) * eb.at(v_iter);
453 eb.at(v_iter) = eb.at(v_iter) + coeffs.at(5) * ecc.at(v_iter);
454 ed.at(v_iter) = edd.at(v_iter) + coeffs.at(3) * ef.at(v_iter);
455 ef.at(v_iter) = ef.at(v_iter) + coeffs.at(4) * edd.at(v_iter);
456 }
457 }
458}
459
460int PronyFitter::GetNumberPolRoots() { return fTotalPolRoots; }
461
462void PronyFitter::SetHarmonics(std::complex<float> *z) {
463 std::memcpy(fz, z, (fExpNumber + 1) * sizeof(std::complex<float>));
464}
465
466void PronyFitter::SetExternalHarmonics(std::vector<std::complex<float>> harmonics) {
467 auto copy_harmonics = harmonics;
468 const std::complex<float> unit = {1., 0.};
469 copy_harmonics.insert(copy_harmonics.begin(), unit);
470 SetHarmonics(&copy_harmonics[0]);
471}
472
473std::complex<float> *PronyFitter::GetHarmonics() { return fz; }
474
475void PronyFitter::MakeInvHarmoMatrix(int signal_length, std::complex<float> **output) {
476
477 std::complex<float> **Zik_arr = new std::complex<float> *[fExpNumber + 1];
478 for (int i = 0; i < fExpNumber + 1; i++) {
479 Zik_arr[i] = new std::complex<float>[fExpNumber + 1];
480 for (int j = 0; j < fExpNumber + 1; j++)
481 Zik_arr[i][j] = {0., 0.};
482 }
483
484 const std::complex<float> unit = {1., 0.};
485 for (int i = 0; i <= fExpNumber; i++) {
486 for (int j = 0; j <= fExpNumber; j++) {
487 std::complex<float> temp = std::conj(fz[i]) * fz[j];
488 if (std::abs(temp - unit) > 1e-3) {
489 Zik_arr[i][j] = static_cast<std::complex<float>>(
490 (std::pow(temp, static_cast<float>(signal_length)) - unit) /
491 (temp - unit));
492 } else {
493 Zik_arr[i][j] = static_cast<std::complex<float>>(signal_length);
494 }
495 }
496 }
497
498 MatrixInversion(Zik_arr, fExpNumber + 1, output);
499
500 if (fIsDebug) {
501 printf("\nInverse Z Matrix\n");
502 for (int i = 0; i <= fExpNumber; i++) {
503 for (int j = 0; j <= fExpNumber; j++) {
504 printf("%e%+ei ", std::real(Zik_arr[i][j]), std::imag(Zik_arr[i][j]));
505 }
506 printf(" ");
507 for (int j = 0; j <= fExpNumber; j++) {
508 printf("%e%+ei ", std::real(output[i][j]), std::imag(output[i][j]));
509 }
510 printf("\n");
511 }
512
513 printf("\nMultiplying\n");
514 for (int i = 0; i <= fExpNumber; i++) {
515 for (int j = 0; j <= fExpNumber; j++) {
516 std::complex<float> temp = {0.0, 0.0};
517 for (int k = 0; k <= fExpNumber; k++)
518 temp += Zik_arr[i][k] * output[k][j];
519 printf("%e%+ei ", std::real(temp), std::imag(temp));
520 }
521 printf("\n");
522 }
523 }
524
525 for (int i = 0; i < fExpNumber + 1; i++)
526 delete[] Zik_arr[i];
527 delete[] Zik_arr;
528}
529
530void PronyFitter::MakeZpowerMatrix(int signal_length, std::complex<float> **output) {
531 for (int i = 0; i < fExpNumber + 1; i++) {
532 output[i][0] = {1.0, 0.0};
533 for (int sample_curr = 1; sample_curr < signal_length;
534 sample_curr++)
535 output[i][sample_curr] = output[i][sample_curr-1] * fz[i];
536 }
537
538 if (fIsDebug) {
539 printf("\nZ power Matrix\n");
540 for (int i = 0; i < fExpNumber + 1; i++) {
541 for (int j = 0; j < signal_length; j++)
542 printf("%e%+ei ", std::real(output[i][j]), std::imag(output[i][j]));
543 printf("\n");
544 }
545 }
546}
547
548void PronyFitter::MakePileUpRejection(int /*time_max*/) {}
549
551 std::complex<float> **Zik_arr = new std::complex<float> *[fExpNumber + 1];
552 for (int i = 0; i < fExpNumber + 1; i++) {
553 Zik_arr[i] = new std::complex<float>[fExpNumber + 1];
554 for (int j = 0; j < fExpNumber + 1; j++)
555 Zik_arr[i][j] = {0., 0.};
556 }
557
558 std::complex<float> *Zyk_arr = new std::complex<float>[fExpNumber + 1];
559 for (int i = 0; i < fExpNumber + 1; i++)
560 Zyk_arr[i] = {0., 0.};
561
562 int samples_in_gate = fGateEnd - fSignalBegin + 1;
563 const std::complex<float> unit = {1., 0.};
564
565 for (int i = 0; i <= fExpNumber; i++) {
566 for (int j = 0; j <= fExpNumber; j++) {
567 std::complex<float> temp = std::conj(fz[i]) * fz[j];
568 if (std::abs(temp - unit) > 1e-3) {
569 Zik_arr[i][j] = static_cast<std::complex<float>>(
570 (std::pow(temp, static_cast<float>(samples_in_gate)) - unit) /
571 (temp - unit));
572 } else {
573 Zik_arr[i][j] = static_cast<std::complex<float>>(samples_in_gate);
574 }
575 }
576 }
577
578 std::complex<float> *z_power = new std::complex<float>[fExpNumber + 1];
579 for (int i = 0; i < fExpNumber + 1; i++)
580 z_power[i] = unit;
581
582 for (int i = 0; i <= fExpNumber; i++) {
583 for (int sample_curr = fSignalBegin; sample_curr <= fGateEnd;
584 sample_curr++) {
585 Zyk_arr[i] += (std::complex<float>)(std::conj(z_power[i]) *
586 (float)fWfm.at(sample_curr));
587 z_power[i] *= fz[i];
588 }
589 }
590
591 if (fIsDebug) {
592 printf("\nampl calculation\n");
593 for (int i = 0; i <= fExpNumber; i++) {
594 for (int j = 0; j <= fExpNumber; j++)
595 printf("%e%+ei ", std::real(Zik_arr[i][j]), std::imag(Zik_arr[i][j]));
596 printf(" fh%i = %e%+ei\n", i, std::real(Zyk_arr[i]), std::imag(Zyk_arr[i]));
597 }
598 }
599
600 SolveSLEGauss(fh, Zik_arr, Zyk_arr, fExpNumber + 1);
601
602 if (fIsDebug) {
603 printf("amplitudes\n%.0f%+.0fi ", std::real(fh[0]), std::imag(fh[0]));
604 for (int i = 1; i < fExpNumber + 1; i++)
605 printf("%e%+ei ", std::real(fh[i]), std::imag(fh[i]));
606 printf("\n\n");
607 }
608
609 for (int i = 0; i < fExpNumber + 1; i++)
610 z_power[i] = unit;
611
612 std::complex<float> fit_ampl_in_sample = {0., 0.};
613 fFitZeroLevel = std::real(fh[0]);
614 for (int sample_curr = 0; sample_curr < fSampleTotal; sample_curr++) {
615 fit_ampl_in_sample = {0., 0.};
616 if ((sample_curr >= fSignalBegin)) { //&& (sample_curr <= fGateEnd)) {
617 for (int i = 0; i < fExpNumber + 1; i++) {
618 fit_ampl_in_sample += fh[i] * z_power[i];
619 z_power[i] *= fz[i];
620 }
621 fFitWfm.at(sample_curr) = std::real(fit_ampl_in_sample);
622 } else
623 fFitWfm.at(sample_curr) = fFitZeroLevel;
624 }
625
626 if (fIsDebug) {
627 printf("waveform:\n");
628 for (uint16_t i = 0; i < fWfm.size(); i++)
629 printf("%f ", fWfm.at(i));
630
631 printf("\nfit waveform:\n");
632 for (uint16_t i = 0; i < fFitWfm.size(); i++)
633 printf("%f ", fFitWfm.at(i));
634
635 printf("\nzero level %f\n\n", fZeroLevel);
636 }
637
638 for (int i = 0; i < fExpNumber + 1; i++)
639 delete[] Zik_arr[i];
640 delete[] Zik_arr;
641 delete[] Zyk_arr;
642 delete[] z_power;
643}
644
645void PronyFitter::CalculateFitAmplitudesFast(int signal_length, std::complex<float> **InvHarmoMatrix) {
646
647 if (fSignalBegin + signal_length > (int)fWfm.size()) {
648 printf ("signal begin %i reaching waveform end! Aborting. Constant signal length %i\n", fSignalBegin, signal_length);
649 return;
650 }
651
652 std::complex<float> *Zyk_arr = new std::complex<float>[fExpNumber + 1];
653 for (int i = 0; i < fExpNumber + 1; i++)
654 Zyk_arr[i] = {0., 0.};
655
656 const std::complex<float> unit = {1., 0.};
657 std::complex<float> *z_power = new std::complex<float>[fExpNumber + 1];
658 for (int i = 0; i < fExpNumber + 1; i++)
659 z_power[i] = unit;
660
661 if (fIsDebug) { printf("composing z power\n"); }
662 for (int i = 0; i <= fExpNumber; i++) {
663 for (int sample_curr = fSignalBegin; sample_curr < fSignalBegin + signal_length;
664 sample_curr++) {
665 Zyk_arr[i] += (std::complex<float>)(std::conj(z_power[i]) *
666 (float)fWfm.at(sample_curr));
667 if (fIsDebug) { printf("%e%+ei ", std::real(z_power[i]), std::imag(z_power[i])); }
668 z_power[i] *= fz[i];
669 }
670 if (fIsDebug) printf("\n");
671 }
672
673 if (fIsDebug) {
674 printf("\nampl calculation fast with signal length %i\n", signal_length);
675 for (int i = 0; i <= fExpNumber; i++) {
676 printf("fh%i = ", i);
677 for (int j = 0; j <= fExpNumber; j++)
678 printf("%e%+ei ", std::real(InvHarmoMatrix[i][j]), std::imag(InvHarmoMatrix[i][j]));
679 printf(" %e%+ei\n", std::real(Zyk_arr[i]), std::imag(Zyk_arr[i]));
680 }
681 }
682
683 for (int i = 0; i <= fExpNumber; i++)
684 for (int j = 0; j <= fExpNumber; j++)
685 fh[i] += InvHarmoMatrix[i][j] * Zyk_arr[j];
686
687 if (fIsDebug) {
688 printf("amplitudes\n%.0f%+.0fi ", std::real(fh[0]), std::imag(fh[0]));
689 for (int i = 1; i < fExpNumber + 1; i++)
690 printf("%e%+ei ", std::real(fh[i]), std::imag(fh[i]));
691 printf("\n\n");
692 }
693
694 for (int i = 0; i < fExpNumber + 1; i++)
695 z_power[i] = unit;
696
697 std::complex<float> fit_ampl_in_sample = {0., 0.};
698 fFitZeroLevel = std::real(fh[0]);
699 for (int sample_curr = 0; sample_curr < fSampleTotal; sample_curr++) {
700 fit_ampl_in_sample = {0., 0.};
701 if ((sample_curr >= fSignalBegin) && (sample_curr <= fGateEnd)) {
702 for (int i = 0; i < fExpNumber + 1; i++) {
703 fit_ampl_in_sample += fh[i] * z_power[i];
704 z_power[i] *= fz[i];
705 }
706 fFitWfm.at(sample_curr) = std::real(fit_ampl_in_sample);
707 } else
708 fFitWfm.at(sample_curr) = fFitZeroLevel;
709 }
710
711 if (fIsDebug) {
712 printf("waveform:\n");
713 for (uint16_t i = 0; i < fWfm.size(); i++)
714 printf("%f ", fWfm.at(i));
715
716 printf("\nfit waveform:\n");
717 for (uint16_t i = 0; i < fFitWfm.size(); i++)
718 printf("%f ", fFitWfm.at(i));
719
720 printf("\nzero level %f\n\n", fZeroLevel);
721 }
722
723 delete[] Zyk_arr;
724 delete[] z_power;
725}
726
727std::complex<float> *PronyFitter::GetAmplitudes() { return fh; }
728
729float PronyFitter::GetIntegral(int gate_beg, int gate_end) {
730 return std::accumulate(fFitWfm.begin() + gate_beg, fFitWfm.begin() + gate_end + 1,
731 -fFitZeroLevel * (gate_end - gate_beg + 1));
732}
733
734float PronyFitter::GetFitValue(int sample_number) {
735 if (std::isfinite(fFitWfm.at(sample_number)))
736 return fFitWfm.at(sample_number);
737 return 0;
738}
739
741 std::complex<float> amplitude = {0., 0.};
742 if (x < GetSignalBeginFromPhase())
743 return std::real(fh[0]);
744 amplitude += fh[0];
745 for (int i = 1; i < fExpNumber + 1; i++)
746 amplitude += fh[i] * std::pow(fz[i], x - fSignalBegin);
747
748 if (std::isfinite(std::real(amplitude)))
749 return std::real(amplitude);
750 return 0;
751}
752
753float PronyFitter::GetZeroLevel() { return (float)fFitZeroLevel; }
754
756 if(fExpNumber == 2){
757 return fSignalBegin + std::real((std::log(-fh[2] * std::log(fz[2])) -
758 std::log(fh[1] * log(fz[1]))) /
759 (std::log(fz[1]) - std::log(fz[2])));
760 }
761 else{
762 auto const max_iter = std::max_element(fFitWfm.begin(), fFitWfm.end());
763 return (float) std::distance(fFitWfm.begin(), max_iter);
764 }
765
766}
767
769 if(fExpNumber == 2){
770 if (std::real(fh[2] / fh[1]) < 0)
771 return fSignalBegin +
772 std::real(std::log(-fh[2] / fh[1]) / std::log(fz[1] / fz[2]));
773 }
774
775 return fSignalBegin;
776}
777
779
780float PronyFitter::GetX(float level, int first_sample, int last_sample) {
781 int step = 0;
782 if (first_sample < last_sample)
783 step = 1;
784 else
785 step = -1;
786 float result_sample = 0.;
787 int sample_to_check = first_sample;
788 float amplitude = 0.;
789 float amplitude_prev = GetFitValue(sample_to_check - step);
790 while ((first_sample - sample_to_check) * (last_sample - sample_to_check) <=
791 0) {
792 amplitude = GetFitValue(sample_to_check);
793 if ((level - amplitude) * (level - amplitude_prev) <= 0) {
794 result_sample =
795 LevelBy2Points(sample_to_check, amplitude, sample_to_check - step,
796 amplitude_prev, level);
797 return result_sample;
798 }
799 amplitude_prev = amplitude;
800 sample_to_check += step;
801 }
802
803 return 0;
804}
805
806float PronyFitter::GetX(float level, int first_sample, int last_sample,
807 float step) {
808 float result_sample = 0.;
809 float sample_to_check = (float)first_sample;
810 std::complex<float> amplitude = {0., 0.};
811 std::complex<float> amplitude_prev = GetFitValue(sample_to_check - step);
812 while ((first_sample - sample_to_check) * (last_sample - sample_to_check) <=
813 0) {
814 amplitude = GetFitValue(sample_to_check);
815 if ((level - std::real(amplitude)) * (level - std::real(amplitude_prev)) <=
816 0) {
817 if (amplitude != amplitude_prev)
818 result_sample = LevelBy2Points(sample_to_check, std::real(amplitude),
819 sample_to_check - step,
820 std::real(amplitude_prev), level);
821 return result_sample;
822 }
823 amplitude_prev = amplitude;
824 sample_to_check += step;
825 }
826
827 return 0;
828}
829
830float PronyFitter::LevelBy2Points(float X1, float Y1, float X2, float Y2,
831 float Y0) {
832 return (X1 * Y0 - X1 * Y2 - X2 * Y0 + X2 * Y1) / (Y1 - Y2);
833}
834
835float PronyFitter::GetRSquare(int gate_beg, int gate_end) {
836 float R2 = 0.;
837 float RSS = 0.;
838 float TSS = 0.;
839 int m = gate_end - gate_beg + 1;
840 int params_number = 1 + 2 * fModelOrder;
841 if (m <= params_number)
842 return 999;
843 float average = 0.;
844 for (int sample_curr = gate_beg; sample_curr <= gate_end; sample_curr++)
845 average += fWfm.at(sample_curr);
846 average /= m;
847
848 for (int sample_curr = gate_beg; sample_curr <= gate_end; sample_curr++) {
849 RSS += std::pow(fFitWfm.at(sample_curr) - fWfm.at(sample_curr), 2);
850 TSS += std::pow(fWfm.at(sample_curr) - average, 2);
851 }
852 if (TSS == 0)
853 return 999;
854 R2 = RSS / TSS; // correct definition is R2=1.-RSS/TSS, but R2=RSS/TSS is more
855 // convenient
856
857 float R2_adj = R2 * (m - 1) / (m - params_number);
858 return R2_adj;
859}
860
862 return GetRSquare(fSignalBegin, fGateEnd);
863}
864
865float PronyFitter::GetChiSquare(int gate_beg, int gate_end, int time_max) {
866 float chi2 = 0.;
867 int freedom_counter = 0;
868 int regions_number = 10;
869 float amplitude_max = std::abs(fWfm.at(time_max) - fZeroLevel);
870 if (amplitude_max == 0)
871 return 999;
872
873 int *probability_exp = new int[regions_number];
874 int *probability_theor = new int[regions_number];
875 float *amplitude_regions = new float[regions_number + 1];
876 amplitude_regions[0] = 0.;
877 for (int i = 0; i < regions_number; i++) {
878 probability_exp[i] = 0;
879 probability_theor[i] = 0;
880 amplitude_regions[i + 1] = (i + 1) * amplitude_max / regions_number;
881 }
882
883 for (int sample_curr = gate_beg; sample_curr <= gate_end; sample_curr++) {
884 for (int i = 0; i < regions_number; i++) {
885 if ((std::abs(fWfm.at(sample_curr) - fZeroLevel) >
886 amplitude_regions[i]) &&
887 (std::abs(fWfm.at(sample_curr) - fZeroLevel) <=
888 amplitude_regions[i + 1]))
889 probability_exp[i]++;
890 if ((std::abs(fFitWfm.at(sample_curr) - fFitZeroLevel) >
891 amplitude_regions[i]) &&
892 (std::abs(fFitWfm.at(sample_curr) - fFitZeroLevel) <=
893 amplitude_regions[i + 1]))
894 probability_theor[i]++;
895 }
896 }
897
898 for (int i = 0; i < regions_number; i++) {
899 if (probability_exp[i] > 0) {
900 chi2 += std::pow(probability_exp[i] - probability_theor[i], 2.) /
901 (probability_exp[i]);
902 freedom_counter++;
903 }
904 }
905
906 if (freedom_counter > 0)
907 chi2 /= freedom_counter;
908 delete[] probability_exp;
909 delete[] probability_theor;
910 delete[] amplitude_regions;
911
912 return chi2;
913}
914
916 return fFitWfm.at(sample) - fWfm.at(sample);
917}
918
920 int last_sample) {
921 float best_R2 = 0.;
922 int best_signal_begin = 0;
923 bool IsReasonableRoot;
924 bool IsGoodFit = false;
925 int good_fit_counter = 0;
926
927 for (int signal_begin = first_sample; signal_begin <= last_sample;
928 signal_begin++) {
929 SetSignalBegin(signal_begin);
931 IsReasonableRoot = true;
932 for (int j = 0; j < fExpNumber; j++)
933 IsReasonableRoot = IsReasonableRoot && (std::abs(fz[j + 1]) > 1e-6) &&
934 (std::abs(fz[j + 1]) < 1e1);
935 IsGoodFit = (fTotalPolRoots > 0) && (IsReasonableRoot);
936
937 if (IsGoodFit) {
938 if (fIsDebug)
939 printf("good fit candidate at signal begin %i\n", signal_begin);
940 good_fit_counter++;
942 float R2 = GetRSquare(fGateBeg, fGateEnd);
943 if (good_fit_counter == 1) {
944 best_R2 = R2;
945 best_signal_begin = signal_begin;
946 }
947 if (R2 < best_R2) {
948 best_R2 = R2;
949 best_signal_begin = signal_begin;
950 }
951 }
952 }
953
954 return best_signal_begin;
955}
956
957int PronyFitter::ChooseBestSignalBegin(int first_sample, int last_sample) {
958 float best_R2 = 0.;
959 int best_signal_begin = first_sample;
960
961 for (int signal_begin = first_sample; signal_begin <= last_sample;
962 signal_begin++) {
963 SetSignalBegin(signal_begin);
965 float R2 = GetRSquare(fGateBeg, fGateEnd);
966 if (signal_begin == first_sample)
967 best_R2 = R2;
968 if (R2 < best_R2) {
969 best_R2 = R2;
970 best_signal_begin = signal_begin;
971 }
972 }
973
974 return best_signal_begin;
975}
976
977int PronyFitter::ChooseBestSignalBeginFast(int first_sample, int last_sample, int signal_length, std::complex<float> **InvHarmoMatrix) {
978 float best_R2 = 0.;
979 int best_signal_begin = first_sample;
980
981 for (int signal_begin = first_sample; signal_begin <= last_sample;
982 signal_begin++) {
983 if (signal_begin + signal_length > (int)fWfm.size()) {
984 printf ("signal begin %i reaching waveform end! Aborting. Constant signal length %i\n", signal_begin, signal_length);
985 continue;
986 }
988 SetSignalBegin(signal_begin);
989 CalculateFitAmplitudesFast(signal_length, InvHarmoMatrix);
990 float R2 = GetRSquare(fGateBeg, fGateEnd);
991 if (signal_begin == first_sample)
992 best_R2 = R2;
993 if (R2 < best_R2) {
994 best_R2 = R2;
995 best_signal_begin = signal_begin;
996 }
997 }
998
999 return best_signal_begin;
1000}
1001
1002int PronyFitter::SearchSignalBeginByHarmo(int first_sample, int last_sample, int signal_length, std::complex<float> **Zpower) {
1003
1004 std::complex<double> *Zyk_arr = new std::complex<double>[fExpNumber + 1];
1005 //const std::complex<double> unit = {1., 0.};
1006 int mode = (std::abs(std::imag(fz[1])) > 0.01)? 1 : 0; //choose whether harmonics are complex (1) or real (0)
1007 if (fIsDebug) printf("search begin in complex (1) or real (0) mode: %i\n", mode);
1008
1009 for (int i = 0; i < fExpNumber + 1; i++)
1010 Zyk_arr[i] = {0., 0.};
1011
1012 // initial Zyk at first_sample signal begin
1013 for (int i = 0; i < fExpNumber + 1; i++) {
1014 for (int sample_curr = first_sample; sample_curr < first_sample + signal_length;
1015 sample_curr++)
1016 Zyk_arr[i] += (std::complex<double>)(std::conj(Zpower[i][sample_curr-first_sample]) *
1017 (float)fWfm.at(sample_curr));
1018 if (fIsDebug) { printf("Zyk[%i] at signal begin %i : %e%+ei ", i, first_sample, std::real(Zyk_arr[i]), std::imag(Zyk_arr[i])); }
1019 }
1020 if (fIsDebug) printf("\n");
1021
1022 std::pair<double,double> prev_pair;
1023 std::pair<double,double> new_pair;
1024 if(mode == 1) prev_pair = std::make_pair( std::abs(std::real(Zyk_arr[1])), std::abs(std::imag(Zyk_arr[1])) );
1025 if(mode == 0) prev_pair = std::make_pair( std::abs(std::real(Zyk_arr[1])), std::abs(std::real(Zyk_arr[2])) );
1026
1027 for (int signal_begin = first_sample+1; signal_begin <= last_sample-signal_length;
1028 signal_begin++) {
1029 for (int i = 0; i < fExpNumber + 1; i++){
1030 // substitute first element
1031 Zyk_arr[i] -= (std::complex<double>)fWfm.at(signal_begin-1);
1032 // reduce z power by 1
1033 Zyk_arr[i] /= (std::complex<double>)std::conj(fz[i]);
1034 // add new wfm point
1035 Zyk_arr[i] += (std::complex<double>)(std::conj(Zpower[i][signal_length-1]) *
1036 (float)fWfm.at(signal_begin + signal_length-1));
1037
1038 if (fIsDebug) { printf("Zyk[%i] at signal begin %i : %e%+ei ", i, signal_begin, std::real(Zyk_arr[i]), std::imag(Zyk_arr[i])); }
1039 }
1040 if (fIsDebug) printf("\n");
1041
1042 if(mode == 1) new_pair = std::make_pair( std::abs(std::real(Zyk_arr[1])), std::abs(std::imag(Zyk_arr[1])) );
1043 if(mode == 0) new_pair = std::make_pair( std::abs(std::real(Zyk_arr[1])), std::abs(std::real(Zyk_arr[2])) );
1044 if ((new_pair.first-prev_pair.first)*(new_pair.second-prev_pair.second) < 0) {
1045 if (fIsDebug) printf("begin candidate at %i \n", signal_begin);
1046 //return signal_begin;
1047 }
1048
1049 prev_pair = new_pair;
1050
1051 }
1052
1053 delete[] Zyk_arr;
1054 return first_sample;
1055}
1056
1057void PronyFitter::SolveSLEGauss(float *x, float **r, float *b, int n) {
1058 bool solvable = true;
1059 int maxRow;
1060 float maxEl, tmp, c;
1061 float **a = new float *[n];
1062 for (int i = 0; i < n; i++) {
1063 a[i] = new float[n + 1];
1064 for (int j = 0; j < n + 1; j++)
1065 a[i][j] = 0.;
1066 }
1067
1068 for (int i = 0; i < n; i++) {
1069 for (int j = 0; j < n; j++)
1070 a[i][j] = r[i][j];
1071 a[i][n] = b[i];
1072 }
1073
1074 for (int i = 0; i < n; i++) {
1075 maxEl = std::abs(a[i][i]);
1076 maxRow = i;
1077 for (int k = i + 1; k < n; k++)
1078 if (abs(a[k][i]) > maxEl) {
1079 maxEl = std::abs(a[k][i]);
1080 maxRow = k;
1081 }
1082
1083 if (maxEl == 0) {
1084 solvable = false;
1085 if (fIsDebug)
1086 printf("SLE has not solution\n");
1087 }
1088
1089 for (int k = i; k < n + 1; k++) {
1090 tmp = a[maxRow][k];
1091 a[maxRow][k] = a[i][k];
1092 a[i][k] = tmp;
1093 }
1094
1095 for (int k = i + 1; k < n; k++) {
1096 c = -a[k][i] / a[i][i];
1097 for (int j = i; j < n + 1; j++) {
1098 if (i == j)
1099 a[k][j] = 0.;
1100 else
1101 a[k][j] += c * a[i][j];
1102 }
1103 }
1104 }
1105
1106 for (int i = n - 1; i >= 0; i--) {
1107 x[i] = a[i][n] / a[i][i];
1108 for (int k = i - 1; k >= 0; k--)
1109 a[k][n] -= a[k][i] * x[i];
1110 }
1111
1112 if (!solvable) {
1113 for (int i = n - 1; i >= 0; i--)
1114 x[i] = 0.;
1115 }
1116
1117 for (int i = 0; i < n; i++)
1118 delete[] a[i];
1119 delete[] a;
1120}
1121
1122void PronyFitter::SolveSLEGauss(std::complex<float> *x, std::complex<float> **r,
1123 std::complex<float> *b, int n) {
1124 bool solvable = true;
1125 int maxRow;
1126 float maxEl;
1127 std::complex<float> tmp, c;
1128 std::complex<float> **a = new std::complex<float> *[n];
1129 for (int i = 0; i < n; i++) {
1130 a[i] = new std::complex<float>[n + 1];
1131 for (int j = 0; j < n + 1; j++)
1132 a[i][j] = {0., 0.};
1133 }
1134
1135 for (int i = 0; i < n; i++) {
1136 for (int j = 0; j < n; j++)
1137 a[i][j] = r[i][j];
1138 a[i][n] = b[i];
1139 }
1140
1141 for (int i = 0; i < n; i++) {
1142 maxEl = std::abs(a[i][i]);
1143 maxRow = i;
1144 for (int k = i + 1; k < n; k++)
1145 if (std::abs(a[k][i]) > maxEl) {
1146 maxEl = std::abs(a[k][i]);
1147 maxRow = k;
1148 }
1149
1150 if (maxEl == 0) {
1151 solvable = false;
1152 if (fIsDebug)
1153 printf("PsdPronyFitter:: SLE has not solution\n");
1154 }
1155
1156 for (int k = i; k < n + 1; k++) {
1157 tmp = a[maxRow][k];
1158 a[maxRow][k] = a[i][k];
1159 a[i][k] = tmp;
1160 }
1161
1162 for (int k = i + 1; k < n; k++) {
1163 c = -a[k][i] / a[i][i];
1164 for (int j = i; j < n + 1; j++) {
1165 if (i == j)
1166 a[k][j] = 0.;
1167 else
1168 a[k][j] += c * a[i][j];
1169 }
1170 }
1171 }
1172
1173 for (int i = n - 1; i >= 0; i--) {
1174 x[i] = a[i][n] / a[i][i];
1175 for (int k = i - 1; k >= 0; k--)
1176 a[k][n] -= a[k][i] * x[i];
1177 }
1178
1179 if (!solvable) {
1180 for (int i = n - 1; i >= 0; i--)
1181 x[i] = {0., 0.};
1182 }
1183
1184 for (int i = 0; i < n; i++)
1185 delete[] a[i];
1186 delete[] a;
1187}
1188
1189void PronyFitter::SolveSLECholesky(float *x, float **a, float *b, int n) {
1190 float temp;
1191 float **u = new float *[n];
1192 for (int i = 0; i < n; i++) {
1193 u[i] = new float[n];
1194 for (int j = 0; j < n; j++)
1195 u[i][j] = 0.;
1196 }
1197
1198 float *y = new float[n];
1199 for (int i = 0; i < n; i++)
1200 y[i] = 0.;
1201
1202 for (int i = 0; i < n; i++) {
1203 temp = 0.;
1204 for (int k = 0; k < i; k++)
1205 temp = temp + u[k][i] * u[k][i];
1206 u[i][i] = std::sqrt(a[i][i] - temp);
1207 for (int j = i; j < n; j++) {
1208 temp = 0.;
1209 for (int k = 0; k < i; k++)
1210 temp = temp + u[k][i] * u[k][j];
1211 u[i][j] = (a[i][j] - temp) / u[i][i];
1212 }
1213 }
1214
1215 for (int i = 0; i < n; i++) {
1216 temp = 0.;
1217 for (int k = 0; k < i; k++)
1218 temp = temp + u[k][i] * y[k];
1219 y[i] = (b[i] - temp) / u[i][i];
1220 }
1221
1222 for (int i = n - 1; i >= 0; i--) {
1223 temp = 0.;
1224 for (int k = i + 1; k < n; k++)
1225 temp = temp + u[i][k] * x[k];
1226 x[i] = (y[i] - temp) / u[i][i];
1227 }
1228
1229 for (int i = 0; i < n; i++)
1230 delete[] u[i];
1231 delete[] u;
1232 delete[] y;
1233}
1234
1236 fSignalBegin = 0;
1237 std::fill(fFitWfm.begin(), fFitWfm.end(), 0);
1238 fFitZeroLevel = 0.;
1239 for (int i = 0; i < fExpNumber + 1; i++)
1240 fh[i] = {0., 0.};
1241}
1242
1243void PronyFitter::DeleteData() {
1244 if(fz) delete[] fz;
1245 if(fh) delete[] fh;
1246}
1247
1248void PronyFitter::Clear() {
1249 fModelOrder = 0;
1250 fExpNumber = 0;
1251 fGateBeg = 0;
1252 fGateEnd = 0;
1253 fSampleTotal = 0;
1254 fZeroLevel = 0.;
1255 fSignalBegin = 0;
1256 fTotalPolRoots = 0;
1257 fWfm.clear();
1258 fFitWfm.clear();
1259 fFitZeroLevel = 0.;
1260 DeleteData();
1261}
1262
1263} // namespace PsdSignalFitting
const Float_t delta
Distance between GEM-stations.
Definition BmnMwpcHit.cxx:8
const Float_t d
Z-ccordinate of the first GEM-station.
Definition BmnMwpcHit.cxx:7
void MatrixInversion(std::complex< float > **A, int order, std::complex< float > **Y)
int i
Definition P4_F32vec4.h:22
__m128 m
Definition P4_F32vec4.h:27
friend F32vec4 log(const F32vec4 &a)
Definition P4_F32vec4.h:123
void polynomComplexRoots(float *wr, float *wi, int n, float *a, int &numr)
void polynomRealRoots(float *rootsArray, int n, float *kf_, int &rootsCount)
void CovarianceDirect(float &rho_f, std::vector< float > &a_f, float &rho_b, std::vector< float > &a_b)
void SetSignalBegin(int SignalBeg)
int SearchSignalBeginByHarmo(int first_sample, int last_sample, int signal_length, std::complex< float > **Zpower)
void SolveSLEGauss(float *x, float **r, float *b, int n)
void CalculateFitAmplitudesFast(int signal_length, std::complex< float > **InvHarmoMatrix)
void SetExternalHarmonics(std::vector< std::complex< float > > harmonics)
void CovarianceQRmod(float &rho_f, std::vector< float > &a_f, float &rho_b, std::vector< float > &a_b)
float GetRSquare(int gate_beg, int gate_end)
float GoToLevel(float Level, int *point, int iterator, int iLastPoint)
void SetHarmonics(std::complex< float > *z)
void SetWaveform(std::vector< float > &Wfm, float ZeroLevel)
int CalcSignalBegin(float front_time_beg_03, float front_time_end)
std::complex< float > * GetHarmonics()
int ChooseBestSignalBeginHarmonics(int first_sample, int last_sample)
int ChooseBestSignalBeginFast(int first_sample, int last_sample, int signal_length, std::complex< float > **InvHarmoMatrix)
std::complex< float > * GetAmplitudes()
float GetFitValue(int sample_number)
int ChooseBestSignalBegin(int first_sample, int last_sample)
float GetDeltaInSample(int sample)
float GetChiSquare(int gate_beg, int gate_end, int time_max)
float GetX(float level, int first_sample, int last_sample)
void Initialize(int model_order, int exponent_number, int gate_beg, int gate_end)
float LevelBy2Points(float X1, float Y1, float X2, float Y2, float Y0)
void MakePileUpRejection(int time_max)
float GetIntegral(int gate_beg, int gate_end)
void MakeInvHarmoMatrix(int signal_length, std::complex< float > **output)
void MakeZpowerMatrix(int signal_length, std::complex< float > **output)
void SolveSLECholesky(float *x, float **a, float *b, int n)