8#include <framework/logging/Logger.h>
9#include <svd/reconstruction/WaveFitter.h>
13#include <boost/math/tools/minima.hpp>
27 array<double, 6> waves;
28 double sumTemplateByTemplate = 0;
29 for (
int i = 0; i < 6; ++i) {
31 sumTemplateByTemplate += waves[i] * waves[i];
34 vector<double> amplitudes(
m_data.size());
35 for (
unsigned int row = 0; row <
m_data.size(); ++row) {
36 double sumDataByTemplate = 0;
37 for (
int i = 0; i < 6; i++) {
38 sumDataByTemplate +=
m_data[row][i] * waves[i];
40 amplitudes[row] = sumDataByTemplate / sumTemplateByTemplate;
43 for (
unsigned int row = 0; row <
m_data.size(); ++row)
44 for (
int i = 0; i < 6; i++) {
47 result += diff * diff;
49 return result /
m_ndf;
58 for (
int i = 0; i < 6; ++i) sum_w2 += w[i] * w[i];
59 double lognorm = 0.5 *
m_data.size() * log(sum_w2);
61 for (
unsigned int row = 0; row <
m_data.size(); ++row) {
63 for (
int i = 1; i < 6; ++i)
64 for (
int j = 0; j < i; ++j) {
65 double cross = w[i] *
m_data[row][j] - w[j] *
m_data[row][i];
70 return lognorm + 0.5 * sum_ksi / sum_w2;
79 B2ERROR(
"SVD::WaveFitterter : Fit required with no data provided.");
92 auto result_low = boost::math::tools::brent_find_minima(
95 double lik_low = result_low.second;
96 auto result_hi = boost::math::tools::brent_find_minima(
99 double lik_hi = result_hi.second;
100 if (lik_low < lik_hi) {
101 double t0_low = result_low.first;
105 double t0_hi = result_hi.first;
118 array<double, 6> waves;
119 double sumTemplateByTemplate = 0;
120 for (
int i = 0; i < 6; ++i) {
122 sumTemplateByTemplate += waves[i] * waves[i];
125 for (
unsigned int row = 0; row <
m_data.size(); ++row) {
126 double sumDataByTemplate = 0;
127 for (
int i = 0; i < 6; i++) {
128 sumDataByTemplate +=
m_data[row][i] * waves[i];
138 for (
int i = 0; i < 6; ++i) {
140 sum_w2 += waveVal * waveVal;
142 double one_by_sqrtSumw2 = 1.0 /
sqrt(sum_w2);
143 for (
unsigned int row = 0; row <
m_data.size(); ++row)
147 double timestep = 0.1 *
m_dt;
149 for (
int i = 0; i < 6; ++i) {
151 dwave_sq += dwave * dwave;
154 for (
unsigned int row = 0; row <
m_data.size(); ++row) {
164 for (
int i = 0; i < 6; ++i) {
166 for (
unsigned int row = 0; row <
m_data.size(); ++row)
175 const unsigned int half_order = 6;
176 const double knots[half_order] = {
177 0.1252334085114689154724414,
178 0.3678314989981801937526915,
179 0.5873179542866174472967024,
180 0.7699026741943046870368938,
181 0.9041172563704748566784659,
182 0.9815606342467192506905491
184 const double weights[half_order] = {
185 0.2491470458134027850005624,
186 0.2334925365383548087608499,
187 0.2031674267230659217490645,
188 0.1600783285433462263346525,
189 0.1069393259953184309602547,
190 0.0471753363865118271946160
192 double span = 0.5 * (upper - lower);
193 double center = 0.5 * (upper + lower);
195 for (
unsigned int iknot = 0; iknot < half_order; ++iknot) {
196 result += weights[iknot] * f(center + span * knots[iknot]);
197 result += weights[iknot] * f(center - span * knots[iknot]);
205 const unsigned int half_order = 10;
206 const double knots[half_order] = {
218 const double weights[half_order] = {
230 double span = 0.5 * (upper - lower);
231 double center = 0.5 * (upper + lower);
233 for (
unsigned int iknot = 0; iknot < half_order; ++iknot) {
234 result += weights[iknot] * f(center + span * knots[iknot]);
235 result += weights[iknot] * f(center - span * knots[iknot]);
243 const double outer =
m_dt;
244 const double inner = 5;
246 auto integrand = [
this](
double t)->
double {
return exp(-
negLogLikelihood(t));};
248 double i1 =
integral20(-outer, -inner, integrand);
251 double i4 =
integral20(inner, outer, integrand);
252 double L_background = 1.0 / (2 * outer) * (i1 + i2 + i3 + i4);
253 double L_signal = 1.0 / (2 * inner) * (i2 + i3);
254 double prob = (L_signal / (L_background + L_signal));
261 const double outer =
m_dt;
263 auto integrand = [
this](
double t)->
double {
return exp(-
negLogLikelihood(t));};
265 double int_total =
integral20(-outer, 0, integrand);
267 double int_inner = 0;
268 if (low * high < 0) {
272 int_inner +=
integral20(low, high, integrand);
274 double int_outer = int_total - int_inner;
275 double LR = int_inner / int_outer;
static double s_default_tau
Default waveform decay time.
double m_fittedTimeError
Error estimate of the fitted time.
std::vector< double > m_fittedAmplitudes
Fitted amplitudes of the sample.
strip_data_type m_fittedData
Fitted values from current fit.
static int s_minimizer_precision
minimizer precision
std::vector< double > m_noises
RMS noise for strips.
strip_data_type m_data
Vector of sextets of APV samples.
double pSignal()
Calculate probability of the hit being a signal, with given priors for signal and background.
void doFit()
Perform fit on the data.
std::vector< double > m_fittedAmplitudeErrors
Fitted amplitude errors.
double m_dt
Time interval between samples.
double wave(double t) const
Get unit waveform value at a given time.
void calculateFitErrors()
Calculate fit errors.
static double integral12(double lower, double upper, std::function< double(double)> f)
High-order Gauss-Legendre quadrature for likelihood integrals.
double negLogLikelihood(double t)
Get negative profile log-likelihood for a given time shift.
static double integral20(double lower, double upper, std::function< double(double)> f)
High-order Gauss-Legendre quadrature for likelihood integrals.
int m_ndf
Degrees of freedom of the fit.
static void setPrecision(int ndigits)
Set precision of the minimzer.
double m_fittedTime
Time from interval (-dt,+dt).
wave_function_type m_wave
Waveform function.
void calculateFittedData()
Calculate fitted data.
void calculateAmplitudes()
Calculate amplitudes.
double lrSignal(double a, double b)
Calculate likelihood ratio Lsignal/Lbackground for acceptance (signal) window given as arguments.
std::array< double, 6 > m_times
Vector of sample times.
double m_fittedLik
Chi2 from the current fit.
bool m_hasFit
Are fit results available?
double Chi(double t)
Get standardized chi2 for a given time shift.
double sqrt(double a)
sqrt for double
Namespace to encapsulate code needed for simulation and reconstrucion of the SVD.