PRD2020/UnfoldSpectrum.cc
Go to the documentation of this file.
1 /* Authors: I. ValiƱo, G. Rodriguez, Alan Coleman, Alex Schulz, F. Fenu
2  based on an original code of H. Dembinski */
3 #include <iostream>
4 #include <iomanip>
5 #include <fstream>
6 #include <cmath>
7 #include <vector>
8 #include <cstring>
9 #include <sstream>
10 #include <TFile.h>
11 #include <TCanvas.h>
12 #include <TMath.h>
13 #include <TF1.h>
14 #include "Math/WrappedTF1.h"
15 #include "Math/Integrator.h"
16 #include <TH1D.h>
17 #include <TNtupleD.h>
18 #include <TMath.h>
19 #include <TMinuit.h>
20 #include <TGraphAsymmErrors.h>
21 #include <TGraphErrors.h>
22 #include <TGraph.h>
23 #include <TAxis.h>
24 #include <TMatrixD.h>
25 #include <TVectorD.h>
26 #include <TApplication.h>
27 #include <TMinuit.h>
28 #include <TImage.h>
29 #include <TROOT.h>
30 #include <TStyle.h>
31 #include <TLegend.h>
32 #include <TFeldmanCousins.h>
33 
34 using namespace std;
37 TAxis* thLgE;
38 TVectorD vecLgE;
39 TMatrixD kmatrix;
40 TAxis* rawAxis_lgE;
42 double InverseSdCalibration(const double, TVectorD );
43 double ScaledErrorFunction(const double, const std::vector<double>&);
44 void TestFormat(string, int);
45 
46 #include "BiasFunctions.hh"
47 #include "ResolutionFunctions.hh"
48 #include "TriggerFunctions.hh"
49 #include "UnfoldUtilities.hh"
50 #include "FittingFunctions.hh"
51 #include "Statistics.hh"
52 
54 double IntXmin;
55 double IntXmax;
57 double exposure;
62 TVectorD parsFit;
63 TVectorD parsErrorsFit;
64 TMatrixD parsCov(20, 20);
65 TVectorD MinuitMinimization(double*, Int_t, bool);
66 void FitFCN(Int_t& npar, Double_t* gin, Double_t& f, Double_t* par, Int_t iflag);
67 double Likelihood(double* pars);
68 void PrintResults(TVectorD, TVectorD);
69 
70 //VV
71 int NPar;
72 
73 //VV
74 double fChi2_lik;
75 int fNdf;
76 TVectorD Chi2_lik(double* pars);
77 int IerFlg;
78 
79 //VV
80 const double EeV = 1e18;
81 
82 int main(int argc, char* argv[]) {
83  if (2 != argc) {
84  PrintUsage(argc);
85  return 0;
86  }
87  LoadParam(argv[1]);
88  string DataFileName = SDFile;
90  Double_t SpectrumMin = mapParameters["SpectrumMin"];
91  Double_t SpectrumMax = mapParameters["SpectrumMax"];
92  Double_t SpectrumBinSize = mapParameters["SpectrumBinSize"];
93  const Int_t BinNum = mapParameters["NumBins"];
94  double SpectrumBins[BinNum + 1];
95  const int Npar = mapParameters["NumParam"];
96  //VV
97  NPar = Npar; // in common on the top of the code
98  double fParFitInit[Npar];
99  parsFit.ResizeTo(Npar);
100  parsErrorsFit.ResizeTo(Npar);
101  IntXmin = mapParameters["MinIntegration"];
102  IntXmax = mapParameters["MaxIntegration"];
103  IntegrationSteps = mapParameters["IntegrationSteps"];
104 
105  if (CodeUsed == "Offline")
106  HeraldAnalysis = false;
107  else
108  HeraldAnalysis = true;
109 
110  for (Int_t i = 0; i < BinNum + 1; i++) {
111  ostringstream convert;
112  convert << i + 1;
113  string nameParameter = "r";
114  nameParameter += convert.str();
115  SpectrumBins[i] = mapParameters[nameParameter.c_str()];
116  }
117 
118  cout << "Input File: " << DataFileName << endl;
119  cout << "Output File: " << OutPutFileName << endl;
120  cout << "Output File Rebinned: " << OutPutFileNameRebinned << endl;
121 
122  int hnbins = round((SpectrumMax - SpectrumMin) / SpectrumBinSize);
123  TH1D* thEnergySpectrum = new TH1D("thEnergySpectrum", "", hnbins, SpectrumMin, SpectrumMax);
124  TH1D* thEnergySpectrum_rebinned = new TH1D("thEnergySpectrum_rebinned", "", BinNum, SpectrumBins); //Check! index of SpectrumBins
125  if (MatrixType == "Standard")
126  exposure = mapParameters["Exposure"];
127  if (MatrixType == "Declination")
128  exposure = DirectionalExposure(mapParameters["AugerLatitude"]*TMath::DegToRad(), mapParameters["MinDeclination"] * TMath::DegToRad(), mapParameters["MaxDeclination"] * TMath::DegToRad());
129  if (MatrixType == "Zenith")
130  exposure = DirectionalExposureZenith(mapParameters["MinZenith"],mapParameters["MaxZenith"]);
131 
132  rawAxis_lgE = thEnergySpectrum->GetXaxis();
133 
134 
135  // Open file with Rec. events
136  vector <double> vLogESD;
137  if (VersionInput == "ICRC2019")
138  ReadEventListICRC2019(vLogESD,thEnergySpectrum, thEnergySpectrum_rebinned, DataFileName);
139  else
140  ReadEventList(vLogESD,thEnergySpectrum, thEnergySpectrum_rebinned, DataFileName);
141 
142 
143  if ("no" != Verbose)
144  cerr << "\nRead in " << thEnergySpectrum->GetEntries() << " events\n" << endl;
145 
146  // *****************************************************
147  // RAW SPECTRUM
148  // *****************************************************
149  int Nbins = thEnergySpectrum->GetNbinsX();
150  raw_lgEs.ResizeTo(Nbins), raw_nevents.ResizeTo(Nbins), raw_flux.ResizeTo(Nbins), raw_staterrlow.ResizeTo(Nbins), raw_staterrup.ResizeTo(Nbins);
151 
152  TGraphAsymmErrors* tgEnergySpectrum = new TGraphAsymmErrors();
153  for (int i = 1; i <= Nbins; ++i) {
154  double binW = thEnergySpectrum->GetBinWidth(i);
155  double we = pow(10, thEnergySpectrum->GetBinCenter(i) + binW / 2) - pow(10, thEnergySpectrum->GetBinCenter(i) - binW / 2);
156  double factor = exposure * we;
157  double lgE = thEnergySpectrum->GetBinCenter(i);
158  double content = thEnergySpectrum->GetBinContent(i) / factor;
159  tgEnergySpectrum->SetPoint(i - 1, lgE, content);
160  double plow, pup;
161  poisson_uncertainty(thEnergySpectrum->GetBinContent(i), plow, pup);
162  tgEnergySpectrum->SetPointError(i - 1, 0., 0., plow / factor, pup / factor);
163  raw_lgEs[i - 1] = lgE;
164  raw_nevents[i - 1] = thEnergySpectrum->GetBinContent(i);
165  raw_flux[i - 1] = content;
166  raw_staterrlow[i - 1] = plow / factor;
167  raw_staterrup[i - 1] = pup / factor;
168  }
169 
170  // *****************************************************************
171  // Rebinned raw spectrum
172  // *****************************************************************
173  int Nbins_rebinned = thEnergySpectrum_rebinned->GetNbinsX();
174  raw_lgEs_rebinned.ResizeTo(Nbins_rebinned), raw_nevents_rebinned.ResizeTo(Nbins_rebinned), raw_flux_rebinned.ResizeTo(Nbins_rebinned), raw_staterrlow_rebinned.ResizeTo(Nbins_rebinned), raw_staterrup_rebinned.ResizeTo(Nbins_rebinned);
175 
176  for (int i = 1; i <= Nbins_rebinned; ++i) {
177 
178  double binW_rebinned = thEnergySpectrum_rebinned->GetBinWidth(i);
179  double we_rebinned = pow(10, thEnergySpectrum_rebinned->GetBinCenter(i) + binW_rebinned / 2) - pow(10, thEnergySpectrum_rebinned->GetBinCenter(i) - binW_rebinned / 2);
180  double factor_rebinned = exposure * we_rebinned;
181  double lgE_rebinned = thEnergySpectrum_rebinned->GetBinCenter(i);
182  double content_rebinned = thEnergySpectrum_rebinned->GetBinContent(i) / factor_rebinned;
183 
184  double plow_rebinned, pup_rebinned;
185  poisson_uncertainty(thEnergySpectrum_rebinned->GetBinContent(i), plow_rebinned, pup_rebinned);
186  raw_lgEs_rebinned[i - 1] = lgE_rebinned;
187  raw_nevents_rebinned[i - 1] = thEnergySpectrum_rebinned->GetBinContent(i);
188  raw_flux_rebinned[i - 1] = content_rebinned;
189  raw_staterrlow_rebinned[i - 1] = plow_rebinned / factor_rebinned;
190  raw_staterrup_rebinned[i - 1] = pup_rebinned / factor_rebinned;
191  }
192 
193  /* Model parameters: */
194  /* 0: normalization; 1: log10(energy) at ankle position; 2: spectral index before ankle; 3 spectra index after ankle;
195  4: log10(energy) at the 1/2 suppression; 5: increment of the spectral index beyond suppression */
196 
197  TF1* FitFunction;
198  FitFunction = new TF1("FittingFunction", FluxModels(modelfunctions.c_str()), SpectrumMin, SpectrumMax, Npar);
199 
200  if (modelfunctions == "StandardMultiSmooth") {
201  if ("no" != Verbose)
202  cerr << "Performing initial fit to StandardMultiSmooth\n";
203  FitFunction->SetParameter(0, mapParameters["par0"]);
204  FitFunction->SetParameter(1, mapParameters["par1"]);
205  FitFunction->SetParameter(2, mapParameters["par2"]);
206  FitFunction->SetParameter(3, mapParameters["par3"]);
207  FitFunction->SetParameter(4, mapParameters["par4"]);
208  FitFunction->SetParameter(5, mapParameters["par5"]);
209  FitFunction->SetParameter(6, mapParameters["par6"]);
210  FitFunction->SetParameter(7, mapParameters["par7"]);
211  }
212  if (modelfunctions == "StandardICRC2015") {
213  if ("no" != Verbose)
214  cerr << "Performing initial fit to StandardICRC2015\n";
215  FitFunction->SetParameter(0, mapParameters["par0"]);
216  FitFunction->SetParameter(1, mapParameters["par1"]);
217  FitFunction->SetParameter(2, mapParameters["par2"]);
218  FitFunction->SetParameter(3, mapParameters["par3"]);
219  FitFunction->SetParameter(4, mapParameters["par4"]);
220  FitFunction->SetParameter(5, mapParameters["par5"]);
221  }
222  if (modelfunctions == "Spectrum2015_2017SmoothAnkle") {
223  if ("no" != Verbose)
224  cerr << "Performing initial fit to Spectrum2015_2017SmoothAnkle\n";
225  FitFunction->SetParameter(0, mapParameters["par0"]);
226  FitFunction->SetParameter(1, mapParameters["par1"]);
227  FitFunction->SetParameter(2, mapParameters["par2"]);
228  FitFunction->SetParameter(3, mapParameters["par3"]);
229  FitFunction->SetParameter(4, mapParameters["par4"]);
230  FitFunction->SetParameter(5, mapParameters["par5"]);
231  }
232  if (modelfunctions == "InfillHard") {
233  if ("no" != Verbose)
234  cerr << "Performing initial fit to InfillHard\n";
235  FitFunction->SetParameter(0, mapParameters["par0"]);
236  FitFunction->SetParameter(1, mapParameters["par1"]);
237  FitFunction->SetParameter(2, mapParameters["par2"]);
238  FitFunction->SetParameter(3, mapParameters["par3"]);
239  }
240  if (modelfunctions == "SpectrumInfillICRC2019") {
241  if ("no" != Verbose)
242  cerr << "Performing initial fit to SpectrumInfillICRC2019\n";
243  FitFunction->SetParameter(0, mapParameters["par0"]);
244  FitFunction->SetParameter(1, mapParameters["par1"]);
245  FitFunction->SetParameter(2, mapParameters["par2"]);
246  FitFunction->SetParameter(3, mapParameters["par3"]);
247  FitFunction->SetParameter(4, mapParameters["par4"]);
248  FitFunction->SetParameter(5, mapParameters["par5"]);
249  FitFunction->SetParameter(6, mapParameters["par6"]);
250 
251  if (mapParameters["MaxZenith"] > 40) {
252  FitFunction->FixParameter(1, mapParameters["par1"]); //lgEbreak
253  FitFunction->FixParameter(3, mapParameters["par3"]); //g0
254  FitFunction->FixParameter(6, mapParameters["par6"]); //dg
255  }
256  }
257  if (modelfunctions == "SpectrumLipari") {
258  if ("no" != Verbose)
259  cerr << "Performing initial fit to SpectrumLipari\n";
260  FitFunction->SetParameter(0, mapParameters["par0"]);
261  FitFunction->SetParameter(1, mapParameters["par1"]);
262  FitFunction->SetParameter(2, mapParameters["par2"]);
263  FitFunction->SetParameter(3, mapParameters["par3"]);
264  FitFunction->SetParameter(4, mapParameters["par4"]);
265  FitFunction->SetParameter(5, mapParameters["par5"]);
266  FitFunction->SetParameter(6, mapParameters["par6"]);
267  FitFunction->SetParameter(7, mapParameters["par7"]);
268 
269  FitFunction->SetParameter(8, mapParameters["par8"]);
270  FitFunction->SetParLimits (8,mapParameters["par8"],mapParameters["par8"]);
271  FitFunction->SetParameter(9, mapParameters["par9"]);
272  FitFunction->SetParLimits (9,mapParameters["par9"],mapParameters["par9"]);
273  FitFunction->SetParameter(10, mapParameters["par10"]);
274  FitFunction->SetParLimits (10,mapParameters["par10"],mapParameters["par10"]);
275  }
276 
277 
278  if ("no" == Verbose)
279  tgEnergySpectrum->Fit(FitFunction, "q");
280  else
281  tgEnergySpectrum->Fit(FitFunction);
282 
283  for (int i = 0; i < Npar; i++) {
284  fParFitInit[i] = FitFunction->GetParameter(i);
285  }
286 
287  // set the upper limit at the 90% CL
288  // we can't do before because the fit of the raw spectrum is a chi2 and
289  // the upper limits changes the initial conditions
290  Nbins = thEnergySpectrum->GetNbinsX();
291  for (int i = 1; i <= Nbins; ++i) {
292  if (thEnergySpectrum->GetBinContent(i)==0){
293  double xerr_lo, xerr_up, yerr_lo, yerr_up;
294  xerr_lo = tgEnergySpectrum->GetErrorXlow(i -1);
295  xerr_up = tgEnergySpectrum->GetErrorXhigh(i -1);
296  yerr_lo = tgEnergySpectrum->GetErrorYlow(i -1);
297  yerr_up = tgEnergySpectrum->GetErrorYhigh(i -1);
298  double plow0, pup0, plow1, pup1;
299  poisson_uncertainty( thEnergySpectrum->GetBinContent(i), plow0, pup0 );
300  FC_UpperLimits( thEnergySpectrum->GetBinContent(i), plow1, pup1 );
301  double fac = pup1/pup0;
302  tgEnergySpectrum->SetPointError(i - 1, xerr_lo, xerr_up, yerr_lo, yerr_up*fac);
303  double dummy = raw_staterrup[i - 1];
304  raw_staterrup[i - 1] = dummy*fac;
305  }
306  }
307  Nbins_rebinned = thEnergySpectrum_rebinned->GetNbinsX();
308  for (int i = 1; i <= Nbins_rebinned; ++i) {
309  if (thEnergySpectrum_rebinned->GetBinContent(i)==0){
310  double plow0, pup0, plow1, pup1;
311  poisson_uncertainty( thEnergySpectrum_rebinned->GetBinContent(i), plow0, pup0 );
312  FC_UpperLimits( thEnergySpectrum_rebinned->GetBinContent(i), plow1, pup1 );
313  double fac = pup1/pup0;
314  double dummy = raw_staterrup_rebinned[i - 1];
315  raw_staterrup_rebinned[i - 1] = dummy*fac;
316  }
317  }
318 
319 
320  // ***************************************************
321  // UNFOLDING starts ....
322  // ***************************************************
323  /* Numerical integration made using a Rienmann sum */
324  //do unfolding, x = lgE, y = count
325 
326  int nbins = round((IntXmax - IntXmin) / thEnergySpectrum->GetBinWidth(1));
327  int N = nbins * IntegrationSteps;
328 
329  thLgE = new TAxis(N, IntXmin, IntXmax);
330  vecLgE.ResizeTo(N);
331  for (int i = 1; i <= N; ++i)
332  vecLgE[i - 1] = thLgE->GetBinCenter(i);
333 
334  TVectorD pCal = GetSDCalPars();
335 
336  double resolutionOffset[2] = {0, 0};
337  kmatrix.ResizeTo(N, N);
338  if (MatrixType == "Standard")
339  kmatrix = kResolutionMatrix(pCal, vecLgE, resolutionOffset);
340  if (MatrixType == "Declination")
341  kmatrix = kResolutionMatrixDD(pCal, vecLgE, mapParameters["AugerLatitude"] * TMath::DegToRad(), mapParameters["MinDeclination"] * TMath::DegToRad(), mapParameters["MaxDeclination"] * TMath::DegToRad());
342  if (MatrixType == "Zenith")
343  kmatrix = kResolutionMatrixZenith(pCal, vecLgE, resolutionOffset);
344 
345 
346  double lgExp = log10(exposure);
347 
348  // Set Initial guess parameters from fit
349  double start[Npar];
350  start[0] = fParFitInit[0] + lgExp; // Special treatment for norm
351 
352  for (int ipar = 1; ipar < Npar; ipar++)
353  start[ipar] = fParFitInit[ipar];
354 
355  UnfoldCorrectionFactor.ResizeTo(N);
356  UnfoldCorrectionFactor = MinuitMinimization(start, Npar, true);
357 
358  // statistics errors due to unfolding.
359  TVectorD unfoldstat(N);
360  TVectorD dlgE(N);
361 
362  for (int i = 0; i < N; ++i) {
363  unfoldstat[i] = sqrt(UnfoldCorrectionFactorCoV[i][i]);
364  dlgE[i] = thLgE->GetBinCenter(1) / 2.;
365  }
366 
367 
368  // *******************************************************************
369  // VV
370  // write the resulting spectrum in the output files (ascii and .root)
371  //
372  // *******************************************************************
373 
374  // output root file
375  string OutPutRootFileName = OutPutFileName+".root";
376  TFile *fRootOut = new TFile(OutPutRootFileName.c_str(),"RECREATE");
377 
378  // VV
379  // function with the fitted parameters
380  for (int i=0; i<Npar; i++){
381  if (i==0) {
382  FitFunction->SetParameter(i,parsFit[i]-log10(exposure));
383  FitFunction->SetParError(i,parsErrorsFit[i]-log10(exposure));
384  } else {
385  FitFunction->SetParameter(i,parsFit[i]);
386  FitFunction->SetParError(i,parsErrorsFit[i]);
387  }
388  }
389 
390  //VV
391  TGraphAsymmErrors* gre_JRaw = new TGraphAsymmErrors();
392  TGraphAsymmErrors* gre_JRawE3 = new TGraphAsymmErrors();
393  TGraphAsymmErrors* gre_J = new TGraphAsymmErrors();
394  TGraphAsymmErrors* gre_JE3 = new TGraphAsymmErrors();
395  TGraph* gr_unf = new TGraph();
396  TGraphAsymmErrors* gre_unf = new TGraphAsymmErrors();
397 
398  // VV: get the unfolding correction
399  // new calculation of unfolding coefficients
400  Nbins = rawAxis_lgE->GetNbins();
401  TVectorD UnfoldCorrectionFactor_Likelihood(Nbins);
402  UnfoldCorrectionFactor_Likelihood = GetCorrectionFactor_Likelihood(vecLgE, kmatrix, &parsFit[0], modelfunctions.c_str(), rawAxis_lgE);
403  TVectorD UnfoldCorrectionFactorError_Likelihood(Nbins);
404  UnfoldCorrectionFactorError_Likelihood = GetCorrectionFactorError_Likelihood(vecLgE, kmatrix, NPar, parsFit, parsErrorsFit, parsCov, modelfunctions.c_str(), rawAxis_lgE);
405 
406  // output ascii file with the spectrum data points
407  ofstream fOut(OutPutFileName.c_str(), ios::out);
408  fOut << "# lg(E/eV) lgE_hw raw_counts exposure[km2 sr yr] J [km-2 sr-1 yr-1 eV-1] lower_sigma[J]_stat upper_sigma[J]_stat unfolding_correction sigma[unfolding_correction]_stat" << endl;
409 
410  for (int i = 0; i < raw_lgEs.GetNoElements(); ++i) {
411 
412  //VV
413  // unfolding coefficients.
414  double factorunfold = UnfoldCorrectionFactor_Likelihood[i];
415  double statunc_factorunfold = UnfoldCorrectionFactorError_Likelihood[i];
416 
417  double nmod = raw_flux[i] * factorunfold;
418  double lowerror = raw_staterrlow[i] * factorunfold;
419  double uperror = raw_staterrup[i] * factorunfold;
420 
421  int Nevents = raw_nevents[i];
422  char buffer2 [100];
423  int n2 = sprintf (buffer2,"%4.2f %3.2f %6d %6.1f %5.4le %5.4le %5.4le %4.3f %4.3f", raw_lgEs[i], thEnergySpectrum->GetBinWidth(i) / 2., Nevents , exposure, nmod ,lowerror, uperror, factorunfold, statunc_factorunfold);
424  fOut << buffer2 << endl;
425 
426  // VV for the output root file
427  double En = pow(10.,raw_lgEs[i]);
428  double JRaw = raw_flux[i];
429  double JRaw_loerr = raw_staterrlow[i];
430  double JRaw_uperr = raw_staterrup[i];
431  double J = JRaw * factorunfold;
432  double J_loerr = JRaw_loerr * factorunfold;
433  double J_uperr = JRaw_uperr * factorunfold;
434  double fac = pow(En,3);
435  gre_JRaw->SetPoint(i, En, JRaw);
436  gre_JRaw->SetPointError(i, 0., 0., JRaw_loerr, JRaw_uperr);
437  gre_JRawE3->SetPoint(i, En, JRaw*fac);
438  gre_JRawE3->SetPointError(i, 0., 0., JRaw_loerr*fac, JRaw_uperr*fac);
439  gre_J->SetPoint(i, En, J);
440  gre_J->SetPointError(i, 0., 0., J_loerr, J_uperr);
441  gre_JE3->SetPoint(i, En, J*fac);
442  gre_JE3->SetPointError(i, 0., 0., J_loerr*fac, J_uperr*fac);
443  gr_unf->SetPoint(i, En, factorunfold);
444  gre_unf->SetPoint(i, En, factorunfold);
445  gre_unf->SetPointError(i, 0., 0., statunc_factorunfold, statunc_factorunfold);
446 
447  }
448 
449  // spectrum data points for the other choice of the bins
450  // note: not further unfolding fit is done
451 
452  //VV
453  TGraphAsymmErrors* gre_JRaw_reb = new TGraphAsymmErrors();
454  TGraphAsymmErrors* gre_JRawE3_reb = new TGraphAsymmErrors();
455  TGraphAsymmErrors* gre_J_reb = new TGraphAsymmErrors();
456  TGraphAsymmErrors* gre_JE3_reb = new TGraphAsymmErrors();
457  TGraph* gr_unf_reb = new TGraph();
458  TGraphAsymmErrors* gre_unf_reb = new TGraphAsymmErrors();
459 
460  // VV: get the unfolding correction
461  TAxis *rawAxis_lgE_reb = thEnergySpectrum_rebinned->GetXaxis();
462  int nbins_reb = rawAxis_lgE_reb->GetNbins();
463  TVectorD UnfoldCorrectionFactor_Likelihood_reb(nbins_reb);
464  UnfoldCorrectionFactor_Likelihood_reb = GetCorrectionFactor_Likelihood(vecLgE, kmatrix, &parsFit[0], modelfunctions.c_str(), rawAxis_lgE_reb);
465  TVectorD UnfoldCorrectionFactorError_Likelihood_reb(nbins_reb);
466  UnfoldCorrectionFactorError_Likelihood_reb = GetCorrectionFactorError_Likelihood(vecLgE, kmatrix, NPar, parsFit, parsErrorsFit, parsCov, modelfunctions.c_str(), rawAxis_lgE_reb);
467 
468  // output ascii file with the spectrum data points
469  ofstream fOutRebinned(OutPutFileNameRebinned.c_str(), ios::out);
470  fOutRebinned << "# lg(E/eV) lgE_hw raw_counts exposure[km2 sr yr] J [km-2 sr-1 yr-1 eV-1] lower_sigma[J]_stat upper_sigma[J]_stat unfolding_correction sigma[unfolding_correction]_stat" << endl;
471 
472  for (int i = 0; i < raw_lgEs_rebinned.GetNoElements(); ++i) {
473 
474  //VV
475  // new calculation of unfolding coefficients.
476  double factorunfold_rebinned = UnfoldCorrectionFactor_Likelihood_reb[i];
477  double statunc_factorunfold_rebinned = UnfoldCorrectionFactorError_Likelihood_reb[i];
478 
479  double nmod_rebinned = raw_flux_rebinned[i] * factorunfold_rebinned;
480  double lowerror_rebinned = raw_staterrlow_rebinned[i] * factorunfold_rebinned;
481  double uperror_rebinned = raw_staterrup_rebinned[i] * factorunfold_rebinned;
482 
483  int Nevents = raw_nevents_rebinned[i];
484  char buffer2 [100];
485  int n2 = sprintf (buffer2,"%4.2f %3.2f %6d %6.1f %5.4le %5.4le %5.4le %4.3f %4.3f", raw_lgEs_rebinned[i], thEnergySpectrum_rebinned->GetBinWidth(i) / 2., Nevents , exposure, nmod_rebinned ,lowerror_rebinned, uperror_rebinned, factorunfold_rebinned, statunc_factorunfold_rebinned);
486  fOutRebinned << buffer2 << endl;
487 
488  // VV for the output root file
489  double En = pow(10.,raw_lgEs_rebinned[i]);
490  double JRaw = raw_flux_rebinned[i];
491  double JRaw_loerr = raw_staterrlow_rebinned[i];
492  double JRaw_uperr = raw_staterrup_rebinned[i];
493  double J = JRaw * factorunfold_rebinned;
494  double J_loerr = JRaw_loerr * factorunfold_rebinned;
495  double J_uperr = JRaw_uperr * factorunfold_rebinned;
496  double fac = pow(En,3);
497  gre_JRaw_reb->SetPoint(i, En, JRaw);
498  gre_JRaw_reb->SetPointError(i, 0., 0., JRaw_loerr, JRaw_uperr);
499  gre_JRawE3_reb->SetPoint(i, En, JRaw*fac);
500  gre_JRawE3_reb->SetPointError(i, 0., 0., JRaw_loerr*fac, JRaw_uperr*fac);
501  gre_J_reb->SetPoint(i, En, J);
502  gre_J_reb->SetPointError(i, 0., 0., J_loerr, J_uperr);
503  gre_JE3_reb->SetPoint(i, En, J*fac);
504  gre_JE3_reb->SetPointError(i, 0., 0., J_loerr*fac, J_uperr*fac);
505  gr_unf_reb->SetPoint(i, En, factorunfold_rebinned);
506  gre_unf_reb->SetPoint(i, En, factorunfold_rebinned);
507  gre_unf_reb->SetPointError(i, 0., 0., statunc_factorunfold_rebinned, statunc_factorunfold_rebinned);
508 
509  }
510 
511  fOutRebinned.close();
512  fOut.close();
514 
515 
516 
517  // *******************************************************************
518  //
519  // Print compact migration matrix
520  //
521  // *******************************************************************
522  if(PrintCompact=="yes")
523  {
524  cout<<"PRODUCING COMPACT MATRIX "<<endl;
525  TF1* FitFunctionFitted;
526  FitFunctionFitted = new TF1("FittingFunctionFitted", FluxModels(modelfunctions.c_str()), SpectrumMin, SpectrumMax, Npar);
527  for (int u=0;u<Npar;u++)
528  {
529  FitFunctionFitted->SetParameter(u,parsFit[u]);
530  }
531  kResolutionMatrixZenith_J(pCal, vecLgE, resolutionOffset,FitFunctionFitted);
532  }
533 
534 
535 
536 
537 
538  // **************************************************************************************************************************************
539 
540  /*
541  In the following we calculate:
542 
543  1) the expected energy spectrum in very small energy bins using the fit function;
544  2) the unfolding coefficients in the energy bins used for the spectrum but in small energy steps
545  (useful to show with a continuous function the behaviour with energy of the unfolding coefficients.
546 
547  Note that the the calculation of the expected energy spectrum is done applying a correction that accounts for the finite
548  energy bin size used for the data. This correction is negligible for energy bins smaller than 0.05.
549  The calculation is done assuming that all the energy bins used for the data have the same size.
550 
551  Note also that the calculation is not valid of the rebinned spectrum. It is not extended to it since sometimes
552  the rebinned spectrum is defined using energy bins of different widths.
553 
554  */
555 
556  TGraph* gr_ffitE3_NoBinSizeCorr = new TGraph();
557  TGraphAsymmErrors* gre_ffitE3_NoBinSizeCorr = new TGraphAsymmErrors();
558  TGraph* gr_ffitE3 = new TGraph();
559  TGraphAsymmErrors* gre_ffitE3 = new TGraphAsymmErrors();
560  TGraph* gr_ffitRawE3 = new TGraph();
561  TGraphAsymmErrors* gre_ffitRawE3 = new TGraphAsymmErrors();
562  TGraph* gr_f_unf = new TGraph();
563  TGraphAsymmErrors* gre_f_unf = new TGraphAsymmErrors();
564  int NbinsX = thEnergySpectrum->GetNbinsX();
565  double xmin = thEnergySpectrum->GetBinLowEdge(1);
566  double xmax = thEnergySpectrum->GetBinLowEdge(NbinsX) + thEnergySpectrum->GetBinWidth(NbinsX);
567  int nnx = 1000;
568  double step = (xmax-xmin)/nnx;
569  step = 0.01;
570  nnx = (xmax-xmin)/step;
571 
572  for (int i=0; i<=nnx; i++){
573  //
574  double logE = xmin + step*i;
575  double En = pow(10.,logE);
576  //
577  // correction for the finite bin size --> fcorr_bin
578  // to correctly visualize Jexp for finite energy bin size
579  // important for 0.1 bins - negligible for bins < 0.05
580  double flogE1 = logE - thEnergySpectrum->GetBinWidth(1)/2;
581  int nl = 10;
582  double step_flogE = thEnergySpectrum->GetBinWidth(1)/nl;
583  double Jint = 0.;
584  for (int l=0; l<nl; l++){
585  double flogE = flogE1 + step_flogE*l + step_flogE/2.;
586  double fDeltaE = (pow(10.,flogE+step_flogE/2.)/1e18 - pow(10.,flogE-step_flogE/2.)/1e18)*1e18;
587  Jint = Jint + FitFunction->Eval(flogE) * fDeltaE;
588  }
589  double DeltaE = ( pow(10.,logE+thEnergySpectrum->GetBinWidth(1)/2.)/1e18
590  - pow(10.,logE-thEnergySpectrum->GetBinWidth(1)/2.)/1e18 ) * 1e18;
591  double Jint_approx = FitFunction->Eval(logE) * DeltaE;
592  double fcorr_bin = Jint / Jint_approx;
593  //
594  //
595  // expected energy spectrum without correction for the finite size of the energy bins
596  double Jexp_nocorr = FitFunction->Eval(logE);
597  double Jexp = Jexp_nocorr * fcorr_bin;
598  //
599  // error on the expected energy spectrum
600  // calculate the derivate of the function with respect to the parameters
601  double dfdpar_ffit[Npar];
602  double x[1]={logE};
603  for (int j=0; j<Npar; j++){
604  dfdpar_ffit[j] = FitFunction->GradientPar(j,x,0.0001);
605  }
606  double ffit_err = 0.;
607  for (int j1=0; j1<Npar; j1++){
608  for (int j2=0; j2<Npar; j2++){
609  ffit_err = ffit_err + dfdpar_ffit[j1]*dfdpar_ffit[j2] * parsCov[j1][j2];
610  }
611  }
612  ffit_err = sqrt(ffit_err);
613  double Jexp_err = ffit_err;
614  //
615  // graphs for the output
616  //
617  double fac = pow(En,3);
618  //
619  // spectrum not corrected for the finite size of the energy bins
620  // it coincides with the fit function
621  gr_ffitE3_NoBinSizeCorr->SetPoint(i, En, Jexp_nocorr*fac);
622  gre_ffitE3_NoBinSizeCorr->SetPoint(i, En, Jexp_nocorr*fac);
623  gre_ffitE3_NoBinSizeCorr->SetPointError(i, 0., 0., Jexp_err*fac, Jexp_err*fac);
624  //
625  // spectrum corrected for the finite size of the energy bins
626  gr_ffitE3->SetPoint(i, En, Jexp*fac);
627  gre_ffitE3->SetPoint(i, En, Jexp*fac);
628  gre_ffitE3->SetPointError(i, 0., 0., Jexp_err*fac, Jexp_err*fac);
629  //
630 
631  // ***
632  // unfolding coefficients calculated for the spectrum energy bin size but in the small steps
633  // of the energy as defined for the loop. Useful to show the behaviour of the unfolding coefficients
634  // when it is graphically superimpose to them
635  //
636  flogE1 = logE - thEnergySpectrum->GetBinWidth(1)/2;
637  double flogE2 = logE + thEnergySpectrum->GetBinWidth(1)/2;
638  int MM = 1;
639  TAxis *thLgE_thEnergySpectrumBin = new TAxis(MM, flogE1, flogE2);
640  //
641  TVectorD UnfoldCorrectionFactor_Likelihood_thEnergySpectrum(MM);
642  UnfoldCorrectionFactor_Likelihood_thEnergySpectrum =
643  GetCorrectionFactor_Likelihood(vecLgE, kmatrix, &parsFit[0], modelfunctions.c_str(), thLgE_thEnergySpectrumBin);
644  //
645  TVectorD UnfoldCorrectionFactorError_Likelihood_thEnergySpectrum(MM);
646  UnfoldCorrectionFactorError_Likelihood_thEnergySpectrum =
648  //
649  double unf_thEnergySpectrum = UnfoldCorrectionFactor_Likelihood_thEnergySpectrum[0];
650  double unf_err_thEnergySpectrum = UnfoldCorrectionFactorError_Likelihood_thEnergySpectrum[0];
651  gr_f_unf->SetPoint(i, En, unf_thEnergySpectrum);
652  gre_f_unf->SetPoint(i, En, unf_thEnergySpectrum);
653  gre_f_unf->SetPointError(i, 0., 0., unf_err_thEnergySpectrum, unf_err_thEnergySpectrum);
654  //
655  // ***
656 
657  // calculate the expected raw energy spectrum
658  fac = pow(En,3);
659  double Jexp_raw = Jexp/unf_thEnergySpectrum;
660  double Jexp_raw_err = Jexp_err/unf_thEnergySpectrum;
661  gr_ffitRawE3->SetPoint(i, En, Jexp_raw*fac);
662  gre_ffitRawE3->SetPoint(i, En, Jexp_raw*fac);
663  gre_ffitRawE3->SetPointError(i, 0., 0., Jexp_raw_err*fac, Jexp_raw_err*fac);
664 
665  }
666 
667  // **************************************************************************************************************************************
668 
669 
670  // tree with the events
671  TTree *tree_ev = new TTree("tree_ev","events");
672  double ESD = 0.;
673  tree_ev->Branch("ESD",&ESD,"ESD/D");
674  for (int l=0; l<vLogESD.size(); l++){
675  double lgESD = vLogESD.at(l);
676  ESD = pow(10.,lgESD);
677  tree_ev->Fill();
678  //cout << lgESD << endl;
679  }
680 
681  // VV
682  // parameters to be saved for the output
683  // other info for the output root file
684  // to be
685  TVectorD tExp(1);
686  tExp(0) = exposure;
687  TVectorD tPar(Npar), tParErr(Npar);
688  for (int i=0; i<Npar; i++){
689  double xpar, xpar_err;
690  if (i==0) {
691  xpar = pow(10., parsFit[0]) / exposure;
692  xpar_err = xpar * log(10) * parsErrorsFit[0];
693  }
694  if (modelfunctions == "SpectrumLipari") {
695  if (i==1 || i==2 || i==3) {
696  xpar = pow(10., parsFit[i]);
697  xpar_err = pow(10., parsFit[i])*log(10)*parsErrorsFit[i];
698  }
699  if (i>3){
700  xpar = parsFit[i];
701  xpar_err = parsErrorsFit[i];
702  }
703  }
704  tPar(i) = xpar;
705  tParErr(i) = xpar_err;
706  }
707 
708  TVectorD tChi2fit(1);
709  TVectorD tNdf(1);
710  tChi2fit(0) = fChi2_lik;
711  tNdf(0) = fNdf;
712  TVectorD tIerFlg(1);
713  tIerFlg(0) = IerFlg;
714 
715 
716  // VV
717  // output root file
718  //
719  tree_ev->Write();
720  //
721  thEnergySpectrum->Write();
722  thEnergySpectrum_rebinned->Write();
723  //
724  gre_JRaw->Write("gre_JRaw");
725  gre_JRawE3->Write("gre_JRawE3");
726  gre_J->Write("gre_J");
727  gre_JE3->Write("gre_JE3");
728  gr_unf->Write("gr_unf");
729  gre_unf->Write("gre_unf");
730  //
731  gre_JRaw_reb->Write("gre_JRaw_reb");
732  gre_JRawE3_reb->Write("gre_JRawE3_reb");
733  gre_J_reb->Write("gre_J_reb");
734  gre_JE3_reb->Write("gre_JE3_reb");
735  gr_unf_reb->Write("gr_unf_reb");
736  gre_unf_reb->Write("gre_unf_reb");
737  //
738  gr_f_unf->Write("gr_f_unf");
739  gre_f_unf->Write("gre_f_unf");
740  gr_ffitE3->Write("gr_ffitE3");
741  gre_ffitE3->Write("gre_ffitE3");
742  gr_ffitRawE3->Write("gr_ffitRawE3");
743  gre_ffitRawE3->Write("gre_ffitRawE3");
744  gr_ffitE3_NoBinSizeCorr->Write("gr_ffitE3_NoBinSizeCorr");
745  gre_ffitE3_NoBinSizeCorr->Write("gre_ffitE3_NoBinSizeCorr");
746  //
747  tPar.Write("par");
748  tParErr.Write("par_err");
749  tChi2fit.Write("Chi2");
750  tNdf.Write("Ndf");
751  tIerFlg.Write("IerFlg");
752  //
753  fRootOut->Close();
754  //
755 
756  return 0;
757 
758 } //close main function
759 
760 
761 TVectorD MinuitMinimization(double* start, Int_t Npar_Minim, bool computeCovStat = true) {
762  const int N = Npar_Minim;
763  TMinuit gMinuit(N);
764  double arglist[10];
765  int ierflg = 0;
766  arglist[0] = -1; // Minuit not verbose
767  gMinuit.SetPrintLevel(1);
768 
769  arglist[0] = 0.5; // Set error param for negative-log-likelihood
770  gMinuit.mnexcm("SET ERR", arglist, 1, ierflg);
771 
772  double step = 0.001;
773 
774  if (modelfunctions == "StandardICRC2015") {
775  gMinuit.mnparm(0, "Norm", start[0], step, 0, 0, ierflg);
776  gMinuit.mnparm(1, "lgEa", start[1], step, 0, 0, ierflg);
777  gMinuit.mnparm(2, "g1", start[2], step, 0, 0, ierflg);
778  gMinuit.mnparm(3, "g2", start[3], step, 0, 0, ierflg);
779  gMinuit.mnparm(4, "lgEs", start[4], step, 0, 0, ierflg);
780  gMinuit.mnparm(5, "Dgamma", start[5], step, 0, 0, ierflg);
781  } else if (modelfunctions == "StandardMultiSmooth") {
782  gMinuit.mnparm(0, "Norm", start[0], step, 0, 0, ierflg);
783  gMinuit.mnparm(1, "lgEa", start[1], step, 0, 0, ierflg);
784  gMinuit.mnparm(2, "lgEx", start[2], step, 0, 0, ierflg);
785  gMinuit.mnparm(3, "lgEs", start[3], step, 0, 0, ierflg);
786  gMinuit.mnparm(4, "g1", start[4], step, 0, 0, ierflg);
787  gMinuit.mnparm(5, "g2", start[5], step, 0, 0, ierflg);
788  gMinuit.mnparm(6, "g3", start[6], step, 0, 0, ierflg);
789  gMinuit.mnparm(7, "g4", start[7], step, 0, 0, ierflg);
790  } else if (modelfunctions == "InfillHard") {
791  gMinuit.mnparm(0, "Norm", start[0], step, 0, 0, ierflg);
792  gMinuit.mnparm(1, "lgEa", start[1], step, 0, 0, ierflg);
793  gMinuit.mnparm(2, "g1", start[2], step, 0, 0, ierflg);
794  gMinuit.mnparm(3, "g2", start[3], step, 0, 0, ierflg);
795  } else if (modelfunctions == "Spectrum2015_2017SmoothAnkle") {
796  gMinuit.mnparm(0, "Norm", start[0], step, 0, 0, ierflg);
797  gMinuit.mnparm(1, "lgEa", start[1], step, 0, 0, ierflg);
798  gMinuit.mnparm(2, "g1", start[2], step, 0, 0, ierflg);
799  gMinuit.mnparm(3, "g2", start[3], step, 0, 0, ierflg);
800  gMinuit.mnparm(4, "lgEs", start[4], step, 0, 0, ierflg);
801  gMinuit.mnparm(5, "Dgamma", start[5], step, 0, 0, ierflg);
802  } else if (modelfunctions == "SpectrumInfillICRC2019") {
803  const bool is55 = (mapParameters["MaxZenith"] > 40);
804  gMinuit.mnparm(0, "Norm", start[0], step, 0, 0, ierflg);
805  gMinuit.mnparm(1, "lgEbreak", start[1], is55 ? 0 : step, 0, 0, ierflg);
806  gMinuit.mnparm(2, "lgEankle", start[2], step, 0, 0, ierflg);
807  gMinuit.mnparm(3, "g0", start[3], is55 ? 0 : step, 0, 0, ierflg);
808  gMinuit.mnparm(4, "g1", start[4], step, 0, 0, ierflg);
809  gMinuit.mnparm(5, "g2", start[5], step, 0, 0, ierflg);
810  gMinuit.mnparm(6, "Dgamma", start[6], is55 ? 0 : step, 0, 0, ierflg);
811  }
812  else if (modelfunctions == "SpectrumLipari") {
813 
814  /*
815  VV
816 
817  Choice of the starting values:
818 
819  1) a first chi2 fit of the raw spectrum is done taking the starting values
820  stored in the configuration file
821 
822  2) the values of the parameters output of the above fit are taken as
823  starting values for the unfolding fit
824 
825  The procedure to set the starting values of the unfolding fit is not good because,
826  at the ankle, the raw spectrum is different from the undolded one and a chi2 fit
827  is not good at the highest energies where one has to use a poissonian p.d.f..
828 
829  This generates several problems and ambiguities and sometimes, when the starting
830  values are cleary wrong, the fit does not converge. The problem emerges when many
831  parameters are fitted (like to include the new feature at 10 EeV) and when the statistics
832  is reduced (e.g. spectrum in different declination bands).
833 
834  For the above reasons, sometimes the starting values in the configuration
835  file are different and sometimes are hardcoded. The starting values below
836  are the ones that have been used for the PRD/PRL papers.
837 
838  For the future it is highly recommended to implement a poissonian fit of the raw
839  spectrum and to not use the output of the fit of the raw spectrum to set the
840  starting values for the fit of the unfolded spectrum.
841 
842  */
843 
844  gMinuit.mnparm(0, "Norm", start[0], step, 0, 0, ierflg);
845  gMinuit.mnparm(1, "lgE12", start[1], step, 0, 0, ierflg);
846  gMinuit.mnparm(2, "lg23", start[2], step, 0, 0, ierflg);
847  gMinuit.mnparm(3, "lg34", start[3], step, 0, 0, ierflg);
848  gMinuit.mnparm(4, "g1", start[4], step, 0, 0, ierflg);
849  gMinuit.mnparm(5, "g2", start[5], step, 0, 0, ierflg);
850  gMinuit.mnparm(6, "g3", start[6], step, 0, 0, ierflg);
851  gMinuit.mnparm(7, "g4", start[7], step, 0, 0, ierflg);
852  gMinuit.mnparm(8, "w12", start[8], 0, start[8], start[8], ierflg);
853  gMinuit.mnparm(9, "w23", start[9], 0, start[9], start[9], ierflg);
854  gMinuit.mnparm(10, "w34", start[10], 0, start[10], start[10], ierflg);
855 
856 
857  Double_t maxDecl = mapParameters["MaxDeclination"];
858  Double_t minDecl = mapParameters["MinDeclination"];
859 
860  if (minDecl==-90. && maxDecl==-42.5){
861  gMinuit.mnparm(0, "Norm", -13.539070, step, 0, 0, ierflg);
862  gMinuit.mnparm(1, "lgE12", 18.711274, step, 0, 0, ierflg);
863  gMinuit.mnparm(2, "lg23", 19.170022, step, 0, 0, ierflg);
864  gMinuit.mnparm(3, "lg34", 19.660508, step, 0, 0, ierflg);
865  gMinuit.mnparm(4, "g1", 3.313246, step, 0, 0, ierflg);
866  gMinuit.mnparm(5, "g2", 2.570759, step, 0, 0, ierflg);
867  gMinuit.mnparm(6, "g3", 3.070131, step, 0, 0, ierflg);
868  gMinuit.mnparm(7, "g4", 4.886723, step, 0, 0, ierflg);
869  }
870 
871  if (minDecl==-17.3 && maxDecl==25.){
872  gMinuit.mnparm(1, "lgE12", log10(5.*EeV), step, log10(3.*EeV), log10(7.*EeV), ierflg);
873  gMinuit.mnparm(2, "lgE23", log10(12.*EeV), step, log10(8.*EeV), log10(16.*EeV), ierflg);
874  gMinuit.mnparm(3, "lgE34", log10(50.*EeV), step, log10(20.*EeV), log10(70.*EeV), ierflg);
875  gMinuit.mnparm(4, "g1", 3.3, step, 0, 0, ierflg);
876  gMinuit.mnparm(5, "g2", 2.5, step, 0, 0, ierflg);
877  gMinuit.mnparm(6, "g3", 3.2, step, 0, 0, ierflg);
878  gMinuit.mnparm(7, "g4", 5.0, step, 3., 7., ierflg);
879  }
880 
881 
882  }
883 
884  gMinuit.SetFCN(FitFCN);
885  // Now ready for minimization step
886  arglist[0] = 1000;
887  arglist[1] = 1.;
888 
889  gMinuit.mnexcm("MINIMIZE", arglist, 2, ierflg);
890  //gMinuit.mnexcm("MIGRAD", arglist, 2, ierflg);
891  IerFlg = ierflg;
892  if ("no" != Verbose)
893  cout << "Minuit error flag: " << ierflg << endl;
894  if (ierflg) {
895  cout << "\t Spectrum fit failed during Minuit." << endl;
896  cout << "\t Change initial conditions or change unfolding function" << endl;
897  throw std::exception();
898  }
899 
900  double fitParameters[N];
901  double fitParErrors[N];
902  for (int i = 0; i < N; i++)
903  gMinuit.GetParameter(i, fitParameters[i], fitParErrors[i]);
904 
905  parsFit.ResizeTo(N);
906 
907  for (int i = 0; i < N; i++) {
908  parsFit[i] = fitParameters[i];
909  parsErrorsFit[i] = fitParErrors[i];
910  }
911 
912  // VV
913  int ncol = vecLgE.GetNoElements();
914  TVectorD CorrFactor(ncol);
915  CorrFactor = GetCorrectionFactor(vecLgE, kmatrix, &fitParameters[0], modelfunctions.c_str());
916 
917  if (computeCovStat) {
918 
919  // covariance matrix
920  // attenzione
921  // la matrice viene riempita shiftando nelle prime posizioni i valori dei parametri effettivamente fittati (non quelli fissi)
922  // di conseguenza l'indice della matrice di covarianza non corrisponde a quello dei parametri
923  // bisogna ritrovare la corrispondenza sapendo quali parametri sono stati fittati
924  //
925  // nota che l'ordine di riempimento viene preservato, ovvero:
926  // il primo parametro libero che si trova nel vettore corrisponde al primo che si trova nella matrice, etc...
927 
928  // matrice come esce da minuit
929  TMatrixD cov_minuit(N, N);
930  gMinuit.mnemat(&cov_minuit[0][0], N);
931 
932  // matrice (da definire) la cui posizione degli elementi corrisponde a quelli del vettore dei parametri
933  TMatrixD cov(N, N);
934  for (int j1=0; j1<N; j1++){
935  for (int j2=0; j2<N; j2++){
936  cov[j1][j2] = 0.;
937  }
938  }
939 
940  int NFreePars = gMinuit.GetNumFreePars();
941  int iPar_cov[NFreePars];
942  int iParFree = -1;
943 
944  for (int i=0; i<N; i++){
945  //cout << i << " " << fitParameters[i] << " +/- " << fitParErrors[i] << " --> " << TMath::Abs(fitParErrors[i]/fitParameters[i]) << endl;
946  if (TMath::Abs(fitParErrors[i]/fitParameters[i])>1e-40) { // fitted parameters. To be improved with a clever method without fitParameters at the denominator
947  iParFree++;
948  // corrispondenza tra l'indice di cov_minuit (iPar_cov) con quello della matrice cov (i)
949  iPar_cov[iParFree] = i;
950  //cout << " --> " << i << " --> " << iParFree << endl;
951  }
952  }
953  //cout << endl;
954 
955  // loop only on the free parameters of parcov_dummy
956  for (int j1=0; j1<NFreePars; j1++){
957  for (int j2=0; j2<NFreePars; j2++){
958  int i1 = iPar_cov[j1];
959  int i2 = iPar_cov[j2];
960  cov[i1][i2] = cov_minuit[j1][j2];
961  }
962  }
963 
964 
965  UnfoldCorrectionFactorCoV.ResizeTo(ncol, ncol);
967  for (int i1=0; i1<N; i1++){
968  for (int i2=0; i2<N; i2++){
969  parsCov[i1][i2] = cov[i1][i2];
970  if (i1==i2){
971  // check
972  //cout << i1 << " " << i2 << " " << sqrt(cov[i1][i2]) << " " << fitParErrors[i1] << endl;
973  if (TMath::Abs(fitParErrors[i1])>0. && TMath::Abs(sqrt(cov[i1][i2])/fitParErrors[i1]-1.)>1e-20 )
974  cout << i1 << " " << i2 << " ERROR --> " << TMath::Abs(sqrt(cov[i1][i2])/fitParErrors[i1]) << endl;
975  }
976  }
977  }
978 
979  // print the correlation coefficient
980  printf("\n");
981  TMatrixD rho(N, N);
982  for (int j1=0; j1<N; j1++){
983  for (int j2=0; j2<N; j2++){
984  rho[j1][j2] = 0.;
985  if (fitParErrors[j1]>0. && fitParErrors[j2]>0.)
986  rho[j1][j2] = parsCov[j1][j2]/fitParErrors[j1]/fitParErrors[j2];
987  }
988  }
989 
990  printf("%5.0d ",0);
991  for (int i2=0; i2<N; i2++)
992  printf("%5.0d ",i2+1);
993  printf("\n");
994  for (int i1=0; i1<N; i1++){
995  printf("%5.0d ",i1+1);
996  for (int i2=0; i2<N; i2++){
997  printf("%5.2f ",rho[i1][i2]);
998  }
999  printf("\n");
1000  }
1001 
1002 
1003  }
1004 
1005 
1006  //
1007  // it calculates also the deviance --> fChi2_lik
1008  double ff = Likelihood(fitParameters);
1009  fNdf = raw_nevents.GetNoElements() - gMinuit.GetNumFreePars();
1010  double pvalue = TMath::Prob(fChi2_lik,(int) fNdf);
1011  double chi2prob = pvalue*1e2;
1012  double nsigma = sqrt(2.) * TMath::ErfInverse(1.-pvalue);
1013  cout << endl;
1014  printf(" -ln(L) = %f \n",ff);
1015  printf(" Chi2 = %f \n",fChi2_lik);
1016  printf(" Ndf = %d \n",(int) fNdf);
1017  printf(" Chi2/Ndf = %f Chi2 prob = %f %% - p-value %le \n", fChi2_lik/fNdf, chi2prob, pvalue );
1018  printf(" n x sigma = %f \n", nsigma);
1019  cout << endl;
1020 
1021  return CorrFactor;
1022 }
1023 
1024 void FitFCN(Int_t& npar, Double_t* gin, Double_t& f, Double_t* par, Int_t iflag) {
1025  f = Likelihood(par);
1026 }
1027 
1028 
1029 double Likelihood(double* pars) {
1030 
1031  int ncol = vecLgE.GetNoElements();
1032  TVectorD mwraws0 = FluxModel(modelfunctions.c_str(), vecLgE, pars); // dN/dE
1033 
1034  for (int i = 0; i < ncol; ++i)
1035  mwraws0[i] = mwraws0[i] * pow(10., vecLgE[i]) * log(10);// dN/dlogE
1036 
1037  TVectorD mwraws = kmatrix * mwraws0;
1038  mwraws *= thLgE->GetBinWidth(1);
1039 
1040  int N = raw_nevents.GetNoElements();
1041  TVectorD mws(N);
1042  mws.Zero();
1043 
1044  for (int i = 0; i < ncol; ++i) {
1045 
1046  double ilgE = vecLgE[i];
1047 
1048  int bin = rawAxis_lgE->FindBin(ilgE);
1049 
1050  if (bin < 1)
1051  continue;
1052 
1053  if (bin > N)
1054  break;
1055 
1056  mws[bin - 1] += mwraws[i] * thLgE->GetBinWidth(1); // expected number of events (delta in poisson distrib.)
1057  }
1058 
1059  TVectorD like(N);
1060  for (int i = 0; i < N; ++i)
1061  like[i] = mws[i] - raw_nevents[i] * log(mws[i]);
1062 
1063 
1064  // deviance
1065  TVectorD Dev(N);
1066  for (int i = 0; i < N; ++i){
1067  double fN = raw_nevents[i];
1068  double fNexp = mws[i];
1069  if (raw_nevents[i]>0){
1070  Dev[i] = 2. * ( (fNexp - fN * log(fNexp)) - (fN - fN * log(fN)) );
1071  } else {
1072  Dev[i] = 2. * ( (fNexp - fN * log(fNexp)) - 0. );
1073  }
1074  }
1075  fChi2_lik = Dev.Sum();
1076 
1077  // neg-log-likelihood fit assuming Poisson fluctuations
1078  return like.Sum();
1079 
1080 }
1081 
1082 
1083 
1084 void PrintResults(TVectorD parsFit, TVectorD parsErrorsFit) {
1085  cout << setprecision(5) << endl;
1086 
1087  double J0 = pow(10., parsFit[0]) / exposure;
1088  double errorJ0 = J0 * log(10) * parsErrorsFit[0];
1089 
1090  if (modelfunctions == "StandardICRC2015") {
1091  cout << endl;
1092  cout << "\t Resulting parameters fitting the regular array flux model (broken PL + smooth suppression): \n" << endl;
1093  cout << "\t Flux normalization: " << J0 << " +- " << errorJ0 << endl;
1094  cout << "\t Eankle: " << pow(10., parsFit[1]) << " +- " << pow(10., parsFit[1])*log(10)*parsErrorsFit[1] << " eV " << endl;
1095  cout << "\t Esuppression: " << pow(10., parsFit[4]) << " +- " << pow(10., parsFit[4])*log(10)*parsErrorsFit[4] << " eV " << endl;
1096  cout << "\t gamma1 " << parsFit[2] << " +- " << parsErrorsFit[2] << endl;
1097  cout << "\t gamma2 " << parsFit[3] << " +- " << parsErrorsFit[3] << endl;
1098  cout << "\t Delta_gamma " << parsFit[5] << " +- " << parsErrorsFit[5] << endl;
1099  cout << "\n" << endl;
1100  } else if (modelfunctions == "StandardMultiSmooth") {
1101  cout << endl;
1102  cout << "\t Resulting parameters fitting the ICRC 2017 folding model (3 breaks PL): \n" << endl;
1103  cout << "\t Flux normalization: " << J0 << " +- " << errorJ0 << endl;
1104  cout << "\t Eankle: " << pow(10., parsFit[1]) << " +- " << pow(10., parsFit[1])*log(10)*parsErrorsFit[1] << " eV " << endl;
1105  cout << "\t Ex: " << pow(10., parsFit[2]) << " +- " << pow(10., parsFit[2])*log(10)*parsErrorsFit[2] << " eV " << endl;
1106  cout << "\t Esuppression: " << pow(10., parsFit[3]) << " +- " << pow(10., parsFit[3])*log(10)*parsErrorsFit[3] << " eV " << endl;
1107  cout << "\t gamma1 " << parsFit[4] << " +- " << parsErrorsFit[4] << endl;
1108  cout << "\t gamma2 " << parsFit[5] << " +- " << parsErrorsFit[5] << endl;
1109  cout << "\t gamma3 " << parsFit[6] << " +- " << parsErrorsFit[6] << endl;
1110  cout << "\t gamma4 " << parsFit[7] << " +- " << parsErrorsFit[7] << endl;
1111  cout << "\n" << endl;
1112  } else if (modelfunctions == "InfillHard") {
1113  cout << endl;
1114  cout << "\t Resulting parameters fitting the Infill array flux model: \n" << endl;
1115  cout << "\t Flux normalization: " << J0 << " +- " << errorJ0 << endl;
1116  cout << "\t Eankle: " << pow(10., parsFit[1]) << " +- " << pow(10., parsFit[1])*log(10)*parsErrorsFit[1] << " eV " << endl;
1117  cout << "\t gamma1 " << parsFit[2] << " +- " << parsErrorsFit[2] << endl;
1118  cout << "\t gamma2 " << parsFit[3] << " +- " << parsErrorsFit[3] << endl;
1119  cout << "\n" << endl;
1120  } else if (modelfunctions == "Spectrum2015_2017SmoothAnkle") {
1121  cout << endl;
1122  cout << "\t Resulting parameters fitting the regular array flux model (Smooth ankle + smooth suppression): \n" << endl;
1123  cout << "\t Flux normalization: " << J0 << " +- " << errorJ0 << endl;
1124  cout << "\t Eankle: " << pow(10., parsFit[1]) << " +- " << pow(10., parsFit[1])*log(10)*parsErrorsFit[1] << " eV " << endl;
1125  cout << "\t Esuppression: " << pow(10., parsFit[4]) << " +- " << pow(10., parsFit[4])*log(10)*parsErrorsFit[4] << " eV " << endl;
1126  cout << "\t gamma1 " << parsFit[2] << " +- " << parsErrorsFit[2] << endl;
1127  cout << "\t gamma2 " << parsFit[3] << " +- " << parsErrorsFit[3] << endl;
1128  cout << "\t Delta_gamma " << parsFit[5] << " +- " << parsErrorsFit[5] << endl;
1129  cout << "\n" << endl;
1130  } else if (modelfunctions == "SpectrumInfillICRC2019") {
1131  cout << endl;
1132  cout << "\t Resulting parameters fitting the ICRC 2019 infill function: \n" << endl;
1133  cout << "\t Flux normalization: " << J0 << " +- " << errorJ0 << endl;
1134  cout << "\t Ebreak: " << pow(10., parsFit[1]) << " +- " << pow(10., parsFit[1])*log(10)*parsErrorsFit[1] << " eV " << endl;
1135  cout << "\t Eankle: " << pow(10., parsFit[2]) << " +- " << pow(10., parsFit[2])*log(10)*parsErrorsFit[2] << " eV " << endl;
1136  cout << "\t gamma0 " << parsFit[3] << " +- " << parsErrorsFit[3] << endl;
1137  cout << "\t gamma1 " << parsFit[4] << " +- " << parsErrorsFit[4] << endl;
1138  cout << "\t gamma2 " << parsFit[5] << " +- " << parsErrorsFit[5] << endl;
1139  cout << "\t dGamma " << parsFit[6] << " +- " << parsErrorsFit[6] << endl;
1140  cout << "\n" << endl;
1141  }
1142  else if (modelfunctions == "SpectrumLipari") {
1143  cout << endl;
1144  // VV
1145  cout << "\n" << endl;
1146  printf(" J0 = (%le +/- %le) \n",J0,errorJ0);
1147  printf(" E12 = (%3.1f +/- %3.1f) x 1e18 eV \n", pow(10., parsFit[1])/EeV, pow(10., parsFit[1])*log(10)*parsErrorsFit[1]/EeV);
1148  printf(" E23 = (%3.1f +/- %3.1f) x 1e18 eV \n", pow(10., parsFit[2])/EeV, pow(10., parsFit[2])*log(10)*parsErrorsFit[2]/EeV);
1149  printf(" E34 = (%3.0f +/- %3.0f) x 1e18 eV \n", pow(10., parsFit[3])/EeV, pow(10., parsFit[3])*log(10)*parsErrorsFit[3]/EeV);
1150  printf(" gamma1 = %3.2f +/- %3.2f \n",parsFit[4],parsErrorsFit[4]);
1151  printf(" gamma2 = %3.2f +/- %3.2f \n",parsFit[5],parsErrorsFit[5]);
1152  printf(" gamma3 = %3.2f +/- %3.2f \n",parsFit[6],parsErrorsFit[6]);
1153  printf(" gamma4 = %3.1f +/- %3.1f \n",parsFit[7],parsErrorsFit[7]);
1154  printf(" w12 = %3.2f +/- %3.2f \n",parsFit[8],parsErrorsFit[8]);
1155  printf(" w23 = %3.2f +/- %3.2f \n",parsFit[9],parsErrorsFit[9]);
1156  printf(" w34 = %3.2f +/- %3.2f \n",parsFit[10],parsErrorsFit[10]);
1157  cout << "\n" << endl;
1158  }
1159 
1160 }
const int Npar
TVectorD raw_staterrup_rebinned
double FluxModel(const modeltype mtype, double *x, double *par)
void PrintUsage(int nArgs)
string OutPutFileNameRebinned
TVectorD raw_lgEs
string PrintCompact
const bool HeraldAnalysis
TMatrixD kResolutionMatrixDD(TVectorD pCal, TVectorD xos, Double_t lat, Double_t deltaMin, Double_t deltaMax)
string Verbose
TMatrixD parsCov(20, 20)
TVectorD parsErrorsFit
const double SpectrumBinSize[2]
TVectorD GetSDCalPars(bool infill=false)
void poisson_uncertainty(double x, double &plow, double &pup)
Definition: Statistics.icc:1
void TestFormat(string, int)
const unsigned int npar
Definition: UnivRec.h:75
vector< t2list > out
output of the algorithm: a list of clusters
Definition: XbAlgo.cc:32
double Likelihood(double *pars)
Double_t DirectionalExposureZenith(Double_t thetaMin, Double_t thetaMax)
TVectorD raw_staterrlow_rebinned
const double SpectrumBins[15][15]
double pow(const double x, const unsigned int i)
double exposure
const double EeV
Definition: GalacticUnits.h:34
TVectorD GetCorrectionFactorError_Likelihood(const TVectorD x, const TMatrixD m, int npar, TVectorD par, TVectorD parerr, TMatrixD parcov, string model, TAxis *fAxis_lgE)
void LoadParam(string paramFileName)
double fChi2_lik
const double IntXmax[2]
const modeltype modelfunctions[2]
TVectorD Chi2_lik(double *pars)
const char nl
Definition: SdInspector.cc:36
map< string, Double_t > mapParameters
string VersionInput
const double IntXmin[2]
TAxis * rawAxis_lgE
TMatrixD UnfoldCorrectionFactorCoV
int main(int argc, char *argv[])
Definition: DBSync.cc:58
TVectorD MinuitMinimization(double *start, bool computeCovStat)
TVectorD raw_flux_rebinned
TVectorD raw_staterrup
double InverseSdCalibration(const double lgE, TVectorD pCal)
TVectorD UnfoldCorrectionFactorMax
string SDFile
double ScaledErrorFunction(const double x, const std::vector< double > &pars)
string OutPutFileName
const double SpectrumMin[2]
TVectorD raw_flux
TVectorD parsFit
TAxis * thLgE
TMatrixD propagate_covariance(TVectorD(*f)(TVectorD, const modeltype), TVectorD x, TMatrixD xcov, const modeltype mtype)
Definition: Statistics.icc:50
void PrintResults()
const int IntegrationSteps
TVectorD UnfoldCorrectionFactorMin
void ReadEventListICRC2019(TH1D *th1, TH1D *th2, string FileName)
double(*)(double *, double *) FluxModels(const modeltype mtype)
void ReadEventList(TH1D *th1, TH1D *th2, string FileName)
TMatrixD kResolutionMatrix(TVectorD pCal, TVectorD xos, double *resolutionOffset, const bool useResFromData, const bool infill)
Double_t DirectionalExposure(Double_t lat, Double_t deltaMin, Double_t deltaMax)
TMatrixD kResolutionMatrixZenith(TVectorD pCal, TVectorD xos, double *resolutionOffset)
TVectorD GetCorrectionFactor_Likelihood(const TVectorD x, const TMatrixD m, double *par, string model, TAxis *frawAxis_lgE)
void kResolutionMatrixZenith_J(TVectorD pCal, TVectorD xos, double *resolutionOffset, TF1 *FitFunctionFitted)
TMatrixD kmatrix
TVectorD raw_staterrlow
const int BinNum[2]
void FitFCN(Int_t &npar, Double_t *gin, Double_t &f, Double_t *par, Int_t iflag)
string CodeUsed
string Model
TVectorD vecLgE
TVectorD raw_lgEs_rebinned
TVectorD UnfoldCorrectionFactor
TVectorD raw_nevents_rebinned
const double SpectrumMax[2]
TVectorD raw_nevents
string MatrixType
double fParFitInit[Npar]
TVectorD GetCorrectionFactor(const TVectorD x, const TMatrixD m, double *par, const modeltype mtype)
void FC_UpperLimits(double x, double &plow, double &pup)

, generated on Tue Sep 26 2023.