UnfoldUtilities.icc
Go to the documentation of this file.
1 /* Utilities to unfold the vertical spectrum such as done for ICRC 2015 */
2 
3 /* Author: I. ValiƱo, based on functions provided by A. Schulz */
4 
5 
6 TVectorD GetSDCalPars(bool infill = false)
7 {
8  //Calibration constants
9  TVectorD pCal(2);
10 
11  if (infill) {
12  if (HeraldAnalysis) {
13  pCal[0] = 1.62710e+16;
14  pCal[1] = 0.9665210;
15  } else {
16  pCal[0] = 1.40738e+16;
17  pCal[1] = 0.9999375;
18  }
19  } else {
20  if (HeraldAnalysis) {
21  pCal[0] = 2.23584e+17;
22  pCal[1] = 0.984078;
23  } else {
24  pCal[0] = 1.78368e+17;
25  pCal[1] = 1.042043;
26  }
27  }
28 
29  return pCal;
30 }
31 
32 
33 double InverseSdCalibration(const double lgE, TVectorD pCal)
34 {
35  return (lgE - log10(pCal[0])) / pCal[1]; /* returns lgS38 or lgS35 */
36 }
37 
38 
39 double ScaledErrorFunction(const double x, const std::vector<double>& pars)
40 {
41  return 0.5 * (1 + TMath::Erf((x - pars[0]) / pars[1]));
42 }
43 
44 
45 double SD1500TriggerEfficiency(const double lgE, const double zenith)
46 {
47 
48  const TVectorD pCal = GetSDCalPars(false);
49 
50  const double pA[4] = {1.18586522, -2.5940793, 3.25692833, -1.19604131};
51  const double cos2th = pow(TMath::Cos(zenith), 2.);
52 
53  const double A = pA[0] + cos2th * pA[1] + cos2th * cos2th * pA[2] + cos2th * cos2th * cos2th * pA[3];
54  const double B = 0.36868343;
55 
56  const double effpars[] = {A, B};
57  const std::vector<double> parvec(effpars, effpars + 2);
58 
59  const double lgS38 = InverseSdCalibration(lgE, pCal);
60  const double feff = ScaledErrorFunction(lgS38, parvec);
61 
62  return feff;
63 }
64 
65 
66 double SD750TriggerEfficiency(const double lgE, const double zenith)
67 {
68  // From simulated Proton showers
69 
70  TVectorD pCal = GetSDCalPars(true);
71 
72  const double pA[4] = {2.38516877, -4.85552037, 4.10415064, -0.97515248};
73  const double cos2th = pow(TMath::Cos(zenith), 2.);
74 
75  const double A = pA[0] + cos2th * pA[1] + cos2th * cos2th * pA[2] + cos2th * cos2th * cos2th * pA[3];
76  const double B = 0.24852449;
77 
78  const double effpars[] = {A, B};
79  const std::vector<double> parvec(effpars, effpars + 2);
80 
81  const double lgS35 = InverseSdCalibration(lgE, pCal);
82  const double feff = ScaledErrorFunction(lgS35, parvec);
83 
84  return feff;
85 }
86 
87 
88 double EfficientZenithDistrib(double* x, double* par)
89 {
90 
91  const double zenith = x[0];
92  const double lgE[1] = {par[0]};
93  const bool infill = par[1];
94 
95  double eff;
96 
97  if (infill)
98  eff = SD750TriggerEfficiency(lgE[0], x[0]);
99  else
100  eff = SD1500TriggerEfficiency(lgE[0], x[0]);
101 
102  return eff * TMath::Cos(zenith) * TMath::Sin(zenith);
103 
104 }
105 
106 
107 double SDTriggerEfficiency(const double lgE, const bool infill)
108 {
109  const double thmax = (infill ? 55. : 60.) * TMath::DegToRad();
110  const double thmin = 0. * TMath::DegToRad();
111 
112  TF1 feff("feff", EfficientZenithDistrib, thmin, thmax, 2);
113  feff.FixParameter(0, lgE);
114  feff.FixParameter(1, infill);
115 
116  ROOT::Math::IntegratorOneDimOptions::SetDefaultAbsTolerance(1.E-6);
117  ROOT::Math::IntegratorOneDimOptions::SetDefaultRelTolerance(1.E-6);
118 
119  ROOT::Math::WrappedTF1 weff(feff);
120  ROOT::Math::Integrator ig(ROOT::Math::IntegrationOneDim::kADAPTIVE);
121  ig.SetFunction(weff);
122 
123  double value_integral = ig.Integral(thmin, thmax);
124  double fnorm = 0.5 * (pow(TMath::Sin(thmax), 2) - pow(TMath::Sin(thmin), 2));
125 
126  return value_integral / fnorm;
127 }
128 
129 
130 TVectorD EnergyBias(TVectorD lgEs, TVectorD pCal, const bool infill)
131 {
132 
133  //const double pars[3] = {0.12287307, -0.10904358, 0.02411047};
134 
135  int ncol = lgEs.GetNoElements();
136  TVectorD biasEnergy(ncol);
137 
138  for (int i = 0; i < ncol; ++i) {
139  if (infill) {
140  biasEnergy[i] = 1.; //No bias for infill
141  } else {
142  // double lgS38 = InverseSdCalibration(lgEs[i], pCal);
143  // double biasS38 = 1 + pars[0] + pars[1] * lgS38 + pars[2] * lgS38 * lgS38;
144  // biasEnergy[i] = pow(biasS38, pCal[1]);
145  biasEnergy[i] = 1.; //No bias for SD
146  }
147  }
148 
149  return biasEnergy;
150 }
151 
152 
156 
157 double SimulationSD1500EnergyResolution(const double lgE, const double zenith)
158 {
159  /* obtained from 50-50 p/Fe simulations using QGSJetII-03 */
160 
161  double p0 = 1.090032150314515363e-01;
162  double p1 = 4.353891452953017049e-01;
163 
164  double Esd = pow(10., lgE);
165 
166  double relErrs = p0 + p1 / sqrt(Esd / 1e+17) ;
167 
168  return relErrs;
169 }
170 
171 double SimulationSD750EnergyResolution(const double lgE, const double zenith)
172 {
173  //new infill resolution model from Daniela
174  //determined together with fd energy bias correction and new invisible energy model
175  //QGSJET 2.4 simulations, quality + FoV cuts, resolution determined for p and Fe
176 
177  const double pars_p[2] = {1.078638367648934449e-01, 1.595403269466228735e-01};
178  const double pars_fe[2] = {4.836779040905066218e-02, 1.697359371453481258e-01};
179  const double pars[2] = {(pars_p[0] + pars_fe[0]) / 2., (pars_p[1] + pars_fe[1]) / 2.};
180 
181  return pars[0] + pars[1] / sqrt(pow(10, lgE) / 1e17);
182 }
183 
184 double DataSD1500EnergyResolution(const double lgE, const double zenith)
185 {
186  /* obtained from data itself */
187  TVectorD pCal = GetSDCalPars(false);
188  const double lgS38 = InverseSdCalibration(lgE, pCal);
189 
190  const double pars[9] = {7.964648011936218460e-04,
191  4.118659698340852438e-01,
192  -1.517612358021901198e+00,
193  9.102368706313619384e+00,
194  -9.938644262370022631e+00,
195  4.120050818744602217e-01,
196  1.244124736151181560e-03,
197  -6.535475475395227107e+00,
198  1.039836139398396853e+01
199  };
200  const double lgsectheta = TMath::Log10(1 / cos(zenith));
201  double res = pars[0] + (pars[1] + pars[2] * lgsectheta + pars[3] * lgsectheta * lgsectheta + pars[4] * lgsectheta * lgsectheta * lgsectheta) * pow(10., -lgS38 * 0.5)
202  + (pars[5] + pars[6] * lgsectheta + pars[7] * lgsectheta * lgsectheta + pars[8] * lgsectheta * lgsectheta * lgsectheta) * pow(10., -lgS38);
203 
204  return res * pCal[1];
205 }
206 
207 
208 double DataSD750EnergyResolution(const double lgE, const double zenith)
209 {
210  TVectorD pCal = GetSDCalPars(true);
211  const double lgS35 = InverseSdCalibration(lgE, pCal);
212 
213  const double pars[6] = {1.713893029281758462e+00, -1.115258876619560580e+00, 1.557604707934408061e+01,
214  6.861112716697782554e-01, -8.015754473911778089e-01, 8.852556156454199909e-01
215  };
216  const double lgsectheta = TMath::Log10(1 / cos(zenith));
217 
218  return (pars[0] + pars[1] * lgsectheta + pars[2] * lgsectheta * lgsectheta)
219  * (pow(10., (-pars[3] * lgS35)) + pars[4] * pow(10., (-pars[5] * lgS35)));
220 }
221 
222 
223 double ResolutionZenithDistrib(double* x, double* par)
224 {
225 
226  const double zenith = x[0];
227  const double lgE = par[0];
228  const bool data = bool(par[1]);
229  const bool infill = bool(par[2]);
230 
231  double res;
232  if (data) {
233  if (infill)
234  res = DataSD750EnergyResolution(lgE, x[0]);
235  else
236  res = DataSD1500EnergyResolution(lgE, x[0]);
237  } else {
238  if (infill)
239  res = SimulationSD750EnergyResolution(lgE, x[0]);
240  else
241  res = SimulationSD1500EnergyResolution(lgE, x[0]);
242  }
243  return res * TMath::Cos(zenith) * TMath::Sin(zenith);
244 }
245 
246 
247 double IntegrateEnergyResolution(const double lgE, const bool data, const bool infill)
248 {
249  const double thmax = (infill ? 55. : 60.) * TMath::DegToRad();
250  const double thmin = 0. * TMath::DegToRad();
251 
252  TF1 fres("fres", ResolutionZenithDistrib, thmin, thmax, 3);
253  fres.FixParameter(0, lgE);
254  fres.FixParameter(1, 1. * data);
255  fres.FixParameter(2, 1. * infill);
256 
257  ROOT::Math::IntegratorOneDimOptions::SetDefaultAbsTolerance(1.E-6);
258  ROOT::Math::IntegratorOneDimOptions::SetDefaultRelTolerance(1.E-6);
259 
260  ROOT::Math::WrappedTF1 wres(fres);
261  ROOT::Math::Integrator ig(ROOT::Math::IntegrationOneDim::kADAPTIVE);
262  ig.SetFunction(wres);
263 
264  double value_integral = ig.Integral(thmin, thmax);
265  double fnorm = 0.5 * (pow(TMath::Sin(thmax), 2) - pow(TMath::Sin(thmin), 2));
266 
267  return value_integral / fnorm;
268 }
269 
270 
271 double CustomShowerToShowerFluctuation(const double lgE)
272 {
273  const double xmin = 16.5;
274  const double xmax = 20.5;
275  const double z = (lgE - xmin) / (xmax - xmin);
276 
277  const double pars[2] = {0.2, 0.0783};
278  double shsh = (1 - z) * pars[0] + z * pars[1];
279  return shsh;
280 }
281 
282 
283 // TODO
285 {
286  double shsh = 0.13;
287  return shsh;
288 }
289 
290 
291 TVectorD EnergyResolution(TVectorD lgEs, const bool data, const bool infill)
292 {
293  int ncol = lgEs.GetNoElements();
294  TVectorD EnergyRes(ncol);
295 
296  for (int i = 0; i < ncol; ++i) {
297  double lgE = lgEs[i];
298  double Esd = pow(10., lgE);
299 
300  double relErrs1 = IntegrateEnergyResolution(lgE, data, infill);
301  double relErrs2 = 0;
302 
303  if (data) {
304  if (infill)
306  else
307  relErrs2 = CustomShowerToShowerFluctuation(lgE);
308  }
309 
310  double relErrs = TMath::Sqrt(pow(relErrs1, 2) + pow(relErrs2, 2));
311 
312  EnergyRes[i] = relErrs * Esd;
313  }
314 
315  return EnergyRes;
316 }
317 
318 
319 TMatrixD kResolutionMatrix(TVectorD pCal, TVectorD xos, double* resolutionOffset, const bool useResFromData, const bool infill)
320 {
321 
322  int N = xos.GetNoElements();
323 
324  TVectorD ses = EnergyResolution(xos, useResFromData, infill);
325 
326  TVectorD Ebias = EnergyBias(xos, pCal, infill);
327 
328  TMatrixD tmp_kmatrix(N, N);
329  for (int i = 0; i < N; ++i) {
330 
331  double ey = pow(10, xos[i]);
332  for (int j = 0; j < N; ++j) {
333 
334  double ex = pow(10, xos[j]);
335  tmp_kmatrix[i][j] = TMath::Gaus(ey, ex * Ebias[j], ses[j], true) * ey * log(10.) * SDTriggerEfficiency(xos[j], infill);
336  }
337  }
338  return tmp_kmatrix;
339 }
const bool HeraldAnalysis
TVectorD EnergyResolution(TVectorD lgEs, const bool data, const bool infill)
double CustomShowerToShowerFluctuation(const double lgE)
double DataSD750EnergyResolution(const double lgE, const double zenith)
double SD1500TriggerEfficiency(const double lgE, const double zenith)
double ResolutionZenithDistrib(double *x, double *par)
double SimulationSD750EnergyResolution(const double lgE, const double zenith)
TVectorD GetSDCalPars(bool infill=false)
double CustomInfillShowerToShowerFluctuation(const double lgE)
double SD750TriggerEfficiency(const double lgE, const double zenith)
double pow(const double x, const unsigned int i)
double IntegrateEnergyResolution(const double lgE, const bool data, const bool infill)
double DataSD1500EnergyResolution(const double lgE, const double zenith)
double SimulationSD1500EnergyResolution(const double lgE, const double zenith)
double InverseSdCalibration(const double lgE, TVectorD pCal)
double SDTriggerEfficiency(const double lgE, const bool infill)
TVectorD EnergyBias(TVectorD lgEs, TVectorD pCal, const bool infill)
double ScaledErrorFunction(const double x, const std::vector< double > &pars)
TMatrixD kResolutionMatrix(TVectorD pCal, TVectorD xos, double *resolutionOffset, const bool useResFromData, const bool infill)
double EfficientZenithDistrib(double *x, double *par)
uint16_t * data
Definition: dump1090.h:228

, generated on Tue Sep 26 2023.