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