PRD2020/FittingFunctions.hh
Go to the documentation of this file.
1 /* FITTING FUNCTIONS */
2 
3 /* Different power-law-like fit functions to describe the measured flux */
4 
5 
6 double SpectrumLgSmoothFitFunction2013(double* x, double* par) {
7 
8  /* ICRC 2013 model:
9 
10  0: J0 (normalization);
11  1: log10(Eankle) (energy in log10 at ankle position);
12  2: gamma1 (spectral index before ankle);
13  3: gamma2 (spectral index after ankle);
14  4: log10(Es) (energy in log10 at the 1/2 suppression);
15  5: log10(Wc) (suppression smoothness )
16  */
17 
18  const double lgE = x[0];
19 
20  double lgJ;
21 
22  if (lgE < par[1])
23  lgJ = par[0] - par[2] * (lgE - par[1]);
24  else {
25  double lgJ_exp = -par[3] * lgE - log10(1.0 + exp((lgE - par[4]) / par[5]));
26  double lgJ_ankle = -par[3] * par[1] - log10(1.0 + exp((par[1] - par[4]) / par[5]));
27  lgJ = par[0] + lgJ_exp - lgJ_ankle;
28  }
29 
30  return pow(10, lgJ);
31 }
32 
33 Double_t Spectrum2015_2017SmoothAnkle(Double_t *v, Double_t *par) {
34  Double_t J;
35  //par[0] J0
36  //par[1] E12
37  //par[2] gamma1
38  //par[3] gamma2
39  //par[4] E23
40  //par[5] Delta gamma
41  double J0 = pow(10, par[0]);
42  double E12 = pow(10, par[1]);
43  double E23 = pow(10, par[4]);
44 
45  double E = pow(10, v[0]);
46 
47  J = pow(E / E12, -par[2]) * ( 1 + pow(E / E12, par[2]) ) / (1 + pow(E / E12, par[3] ) ) * (1. + pow(E12 / E23, par[5]) ) / (1 + pow(E / E23, par[5]));
48 
49  J *= J0;
50  return J;
51 }
52 
53 
54 double SpectrumLgSmoothFitFunction2015(double* x, double* par) {
55 
56  /* ICRC 2015/2017 model:
57 
58  0: J0 (normalization);
59  1: log10(Eankle) (energy in log10 at ankle position);
60  2: gamma1 (spectral index before ankle);
61  3: gamma2 (spectral index after ankle);
62  4: log10(Es) (energy in log10 at the 1/2 suppression);
63  5: Delta gamma (increment of the spectral index beyond suppression)
64  */
65 
66 
67  const double lgE = x[0];
68 
69  double lgJ;
70 
71  if (lgE < par[1])
72  lgJ = par[0] - par[2] * (lgE - par[1]);
73  else {
74  double E = pow(10., lgE);
75  double Ea = pow(10, par[1]);
76  double Es = pow(10, par[4]);
77 
78  double lgJ_exp = log10(1.0 + pow(E / Es, par[5]));
79  double lgJ_ankle = log10(1.0 + pow(Ea / Es, par[5]));
80  lgJ = par[0] - par[3] * (lgE - par[1]) + lgJ_ankle - lgJ_exp ;
81  }
82 
83  return pow(10, lgJ);
84 }
85 
86 
87 double
88 FluxModelMultiSmoothBreak(double* x, double* par) {
89  /* ICRC 2017? model for unfolding (not for spectrum fit):
90  Smooth model with additional break as proposed by Oliver
91  Should be used only for the unfolding to avoid non-diff features in correction factor
92 
93  0: J0 (normalization);
94  1: log10(Eankle) (energy in log10 at ankle position);
95  2: log10(Ex) (energy in log10 at additional break);
96  3: log10(Es) (energy in log10 at the 1/2 suppression);
97  4: gamma1 (spectral index before ankle);
98  5: gamma2 (spectral index after ankle but before x-break);
99  6: gamma3 (spectral index after x-break but before suppression);
100  7: gamma4 (spectral index after suppression);
101 
102  */
103  const size_t n = 8;
104  const size_t breaks = n / 2 - 1;
105  const double lgE = x[0];
106 
107  double lgJ = par[0] - par[breaks + 1] * (lgE - 18.5);
108 
109  for (size_t i = 1; i <= breaks; ++i) {
110  lgJ += TMath::Log10(1 + pow(10, par[breaks + i] * (lgE - par[i])));
111  lgJ -= TMath::Log10(1 + pow(10, par[breaks + i + 1] * (lgE - par[i])));
112  }
113 
114  return pow(10, lgJ);
115 }
116 
117 
118 double SpectrumInfillFitFunction(double* x, double* par) {
119  // Model: only upto ankle --> J0, Eank, gamma1, gamma2
120 
121  const double lgE = x[0];
122 
123  double lgJ;
124 
125  if (lgE < par[1])
126  lgJ = par[0] - par[2] * (lgE - par[1]);
127  else
128  lgJ = par[0] - par[3] * (lgE - par[1]);
129 
130  return pow(10, lgJ);
131 }
132 
133 double SpectrumInfillICRC2019(double* x, double* par) {
134  /*
135  0: J0 (normalization at break)
136  1: log10(E0)
137  2: log10(Eankle)
138  3: gamma0
139  4: gamma1
140  5: gamma2
141  6: dGamma0
142  */
143 
144  const double lgNorm = par[0];
145  const double lgEbreak = par[1];
146  const double lgEa = par[2];
147  const double gamma0 = par[3];
148  const double gamma1 = par[4];
149  const double gamma2 = par[5];
150  const double rate = par[6];
151 
152  const double lgE = x[0];
153 
154  //Maybe one day we can actually fit curve
155  //For now, set to infinity
156  const double lgEs = 1000000;//log10(39.e18);
157  const double dGamma = 2.5;
158 
159  double lgJ;
160 
161  if (lgE < lgEa) {
162  const double factor = pow(10, lgE) / pow(10, lgEbreak);
163  lgJ = lgNorm - gamma0 * (lgE - lgEbreak) + (gamma0 - gamma1) / rate * log10(1 + pow(factor, rate));
164  } else {
165  const double factor = pow(10, lgEa) / pow(10, lgEbreak);
166  double E = pow(10., lgE);
167  double Ea = pow(10, lgEa);
168  double Es = pow(10, lgEs);
169  double lgJ_exp = log10(1.0 + pow(E / Es, dGamma));
170  double lgJ_ankle = log10(1.0 + pow(Ea / Es, dGamma));
171  lgJ = lgNorm - gamma0 * (lgEa - lgEbreak) + (gamma0 - gamma1) / rate * log10(1 + pow(factor, rate)) - gamma2 * (lgE - lgEa) + lgJ_ankle - lgJ_exp;
172  }
173 
174  return pow(10, lgJ);
175 }
176 
177 Double_t SpectrumLipari(double* x, double* par)
178 {
179  /*
180  0: J0
181  1: E12
182  2: gamma1
183  3: E23
184  4: gamma2
185  5: E34
186  6: gamma3
187  7: gamma4
188  8: w12
189  9: w23
190  10: w34
191  */
192  double lgE = x[0];
193  double w[3] = {par[8],par[9],par[10]};
194  double J = par[0] - par[4] * (lgE - 18.5);
195  double factor = (par[4] - par[5]) * w[0];//
196  factor *= log10( 1. + pow(10,(lgE - par[1]) / w[0] ) );
197  J += factor;
198  factor = (par[5] - par[6]) * w[1];//
199  factor *= log10( 1. + pow(10,(lgE - par[2]) / w[1] ) );
200  J += factor;
201  factor = (par[6] - par[7]) * w[2];//
202  factor *= log10( 1. + pow(10,(lgE - par[3]) / w[2] ) );
203 
204  J += factor;
205 
206  return pow(10,J);
207 }
208 
209 
210 
211 // TVectorD versions of the above functions
212 TVectorD SpectrumLgSmoothFitFunction2013(TVectorD x, double* par) {
213  int ncol = x.GetNoElements();
214  TVectorD J(ncol);
215 
216  for (int i = 0; i < ncol; ++i)
217  J[i] = SpectrumLgSmoothFitFunction2013(&x[i], par);
218 
219  return J;
220 }
221 
222 
223 TVectorD SpectrumLgSmoothFitFunction2015(TVectorD x, double* par) {
224  int ncol = x.GetNoElements();
225  TVectorD J(ncol);
226 
227  for (int i = 0; i < ncol; ++i)
228  J[i] = SpectrumLgSmoothFitFunction2015(&x[i], par);
229 
230  return J;
231 }
232 
233 TVectorD Spectrum2015_2017SmoothAnkle(TVectorD x, double* par) {
234  int ncol = x.GetNoElements();
235  TVectorD J(ncol);
236 
237  for (int i = 0; i < ncol; ++i)
238  J[i] = Spectrum2015_2017SmoothAnkle(&x[i], par);
239 
240  return J;
241 }
242 
243 TVectorD FluxModelMultiSmoothBreak(TVectorD x, double* par) {
244  int ncol = x.GetNoElements();
245  TVectorD J(ncol);
246 
247  for (int i = 0; i < ncol; ++i)
248  J[i] = FluxModelMultiSmoothBreak(&x[i], par);
249 
250  return J;
251 }
252 
253 
254 TVectorD SpectrumInfillFitFunction(TVectorD x, double* par) {
255  int ncol = x.GetNoElements();
256  TVectorD J(ncol);
257 
258  for (int i = 0; i < ncol; ++i)
259  J[i] = SpectrumInfillFitFunction(&x[i], par);
260 
261  return J;
262 }
263 
264 
265 TVectorD SpectrumInfillICRC2019(TVectorD x, double* par) {
266  int ncol = x.GetNoElements();
267  TVectorD J(ncol);
268 
269  for (int i = 0; i < ncol; ++i)
270  J[i] = SpectrumInfillICRC2019(&x[i], par);
271 
272  return J;
273 }
274 
275 TVectorD SpectrumLipari(TVectorD x, double* par)
276 {
277  int ncol = x.GetNoElements();
278  TVectorD J(ncol);
279 
280  for (int i = 0; i < ncol; ++i)
281  J[i] = SpectrumLipari(&x[i], par);
282 
283  return J;
284 
285 }
286 
287 
288 
289 // selects one of the implemented models according to the modeltype
290 TVectorD FluxModel(string model, TVectorD x, double* par) {
291  if (model == "StandardICRC2013")
292  return SpectrumLgSmoothFitFunction2013(x, par);
293  else if (model == "StandardICRC2015")
294  return SpectrumLgSmoothFitFunction2015(x, par);
295  else if (model == "StandardMultiSmooth")
296  return FluxModelMultiSmoothBreak(x, par);
297  else if (model == "InfillHard")
298  return SpectrumInfillFitFunction(x, par);
299  else if (model == "Spectrum2015_2017SmoothAnkle")
300  return Spectrum2015_2017SmoothAnkle(x, par);
301  else if (model == "SpectrumInfillICRC2019")
302  return SpectrumInfillICRC2019(x, par);
303  else if (model == "SpectrumLipari")
304  return SpectrumLipari(x, par);
305  else {
306  cerr << endl;
307  cerr << model << ": no valid unfolding function chosen " << endl;
308  throw std::exception();
309  }
310 
311  return SpectrumLgSmoothFitFunction2013(x, par);
312 }
313 
314 double
315 (*FluxModels(string model))(double*, double*) {
316 
317  if (model == "StandardICRC2013")
319  else if (model == "StandardICRC2015")
321  else if (model == "StandardMultiSmooth")
323  else if (model == "InfillHard")
325  else if (model == "Spectrum2015_2017SmoothAnkle")
327  else if (model == "SpectrumInfillICRC2019")
328  return &SpectrumInfillICRC2019;
329  else if (model == "SpectrumLipari")
330  return &SpectrumLipari;
331  else {
332  cerr << endl;
333  cerr << model << ": no valid unfolding function chosen " << endl;
334  throw std::exception();
335  }
336 
338 
339 }
340 
341 
342 TVectorD GetCorrectionFactor(const TVectorD x, const TMatrixD m, double* par, string model) {
343  int ncol = x.GetNoElements();
344  TVectorD f0s = FluxModel(model, x, par);
345 
346  for (int i = 0; i < ncol; ++i)
347  f0s[i] = f0s[i] * pow(10, x[i]);
348 
349  TVectorD f1s = m * f0s;
350  f1s *= (x[1] - x[0]);
351 
352  TVectorD corr(ncol);
353  for (int i = 0; i < ncol; ++i)
354  corr[i] = f0s[i] / f1s[i];
355 
356  return corr;
357 
358 }
359 
360 
361 TVectorD GetCorrectionFactor(TVectorD parsFit, string model) {
362  int ncol = vecLgE.GetNoElements();
363 
364  double* par = &parsFit[0];
365  TVectorD f0s = FluxModel(model, vecLgE, par);
366 
367  for (int i = 0; i < ncol; ++i)
368  f0s[i] = f0s[i] * pow(10, vecLgE[i]);
369 
370  TVectorD f1s = kmatrix * f0s;
371  f1s *= (vecLgE[1] - vecLgE[0]);
372 
373  TVectorD corr(ncol);
374  for (int i = 0; i < ncol; ++i)
375  corr[i] = f0s[i] / f1s[i];
376 
377  return corr;
378 }
379 
380 
381 TVectorD GetCorrectionFactor_Likelihood(const TVectorD x, const TMatrixD m, double* par,string model, TAxis *frawAxis_lgE) {
382 
383  int ncol = x.GetNoElements();
384  TVectorD f0s = FluxModel(model, x, par);
385 
386  for (int i = 0; i < ncol; ++i)
387  f0s[i] = f0s[i] * pow(10, x[i]);
388 
389  TVectorD f1s = m * f0s;
390  f1s *= (x[1] - x[0]);
391 
392 /* TVectorD corr(ncol);
393  for (int i = 0; i < ncol; ++i)
394  corr[i] = f0s[i] / f1s[i];
395 */
396  int N = frawAxis_lgE->GetNbins();
397  TVectorD mws(N);
398  mws.Zero();
399  TVectorD mws0(N);
400  mws0.Zero();
401 
402  TVectorD corr_new(N);
403  for (int i = 0; i < ncol; ++i) {
404  double ilgE = vecLgE[i];
405  int bin = frawAxis_lgE->FindBin(ilgE);
406 
407  if (bin < 1)
408  continue;
409 
410  if (bin > N)
411  break;
412 
413  //cout << vecLgE[i] << " " << bin << endl;
414  mws[bin - 1] += f1s[i]; // expected number of events (delta in poisson distrib.)
415  mws0[bin - 1] += f0s[i]; // expected 'true' number of events (delta in poisson distrib.)
416  }
417 
418  for (int j = 0; j < N; ++j){
419  corr_new[j] = mws0[j]/mws[j];
420  }
421 
422  return corr_new;
423 
424 }
425 
426 TVectorD GetCorrectionFactorError_Likelihood(const TVectorD x, const TMatrixD m, int npar, TVectorD par, TVectorD parerr, TMatrixD parcov, string model, TAxis *fAxis_lgE) {
427  //
428  int Nbins = fAxis_lgE->GetNbins();
429  TVectorD UnfoldCorrectionFactor_Likelihood(Nbins);
430  UnfoldCorrectionFactor_Likelihood = GetCorrectionFactor_Likelihood(x, m, &par[0], model.c_str(), fAxis_lgE);
431 
432  //
433  TVectorD UnfoldCorrectionFactorError_Likelihood(Nbins);
434  //
435  for (int j = 0; j < Nbins; ++j){
436  //
437  double dunf_dp[npar];
438  for (int k=0; k<npar; k++){
439  //
440  dunf_dp[k] = 0.;
441  //
442  TVectorD fpar;
443  fpar.ResizeTo(npar);
444  for (int l=0; l<npar; l++){
445  fpar[l] = par[l];
446  }
447  double ff = 1.;
448  fpar[k] = par[k] + parerr[k]*ff;
449  //fpar[k] = par[k] *(1.+1e-2);
450  //cout << k << " " << parerr[k]*ff << endl;
451  TVectorD UnfoldCorrectionFactor_Likelihood_1(Nbins);
452  UnfoldCorrectionFactor_Likelihood_1 = GetCorrectionFactor_Likelihood(x, m, &fpar[0], model.c_str(), fAxis_lgE);
453  //
454  if (parerr[k]>0)
455  dunf_dp[k] = (UnfoldCorrectionFactor_Likelihood[j] - UnfoldCorrectionFactor_Likelihood_1[j]) / (fpar[k]-par[k]);
456  //
457  }
458  //
459  double unf_err = 0;
460  for (int k1=0; k1<npar; k1++){
461  for (int k2=0; k2<npar; k2++){
462  unf_err = unf_err + dunf_dp[k1]*dunf_dp[k2] * parcov[k1][k2];
463  }
464  }
465  if (unf_err>0.){
466  unf_err = sqrt(unf_err);
467  } else {
468  unf_err = 0.;
469  }
470  //
471  // VV
472  // avoid to0 small errors in the unfolding coefficients
473  // (it does not affect the results)
474  double err_th = 0.15/1e2;
475  if (unf_err<err_th) unf_err = err_th;
476  UnfoldCorrectionFactorError_Likelihood[j] = unf_err;
477  //
478  //cout << j << " " << fAxis_lgE->GetBinCenter(j+1) << " " << UnfoldCorrectionFactor_Likelihood[j] << " " << UnfoldCorrectionFactorError_Likelihood[j] << " --> error in % = " << UnfoldCorrectionFactorError_Likelihood[j]/UnfoldCorrectionFactor_Likelihood[j]*1e2 << endl;
479  }
480 
481  return UnfoldCorrectionFactorError_Likelihood;
482 
483 }
double FluxModel(const modeltype mtype, double *x, double *par)
double SpectrumInfillFitFunction(double *x, double *par)
const unsigned int npar
Definition: UnivRec.h:75
double pow(const double x, const unsigned int i)
TVectorD GetCorrectionFactorError_Likelihood(const TVectorD x, const TMatrixD m, int npar, TVectorD par, TVectorD parerr, TMatrixD parcov, string model, TAxis *fAxis_lgE)
double FluxModelMultiSmoothBreak(double *x, double *par)
Double_t Spectrum2015_2017SmoothAnkle(Double_t *v, Double_t *par)
Double_t SpectrumLipari(double *x, double *par)
TVectorD parsFit
double(*)(double *, double *) FluxModels(const modeltype mtype)
TVectorD GetCorrectionFactor_Likelihood(const TVectorD x, const TMatrixD m, double *par, string model, TAxis *frawAxis_lgE)
double SpectrumLgSmoothFitFunction2013(double *x, double *par)
TMatrixD kmatrix
double SpectrumInfillICRC2019(double *x, double *par)
TVectorD vecLgE
constexpr double m
Definition: AugerUnits.h:121
TVectorD GetCorrectionFactor(const TVectorD x, const TMatrixD m, double *par, const modeltype mtype)
double SpectrumLgSmoothFitFunction2015(double *x, double *par)

, generated on Tue Sep 26 2023.