GaisserHillas4Parameter.cc
Go to the documentation of this file.
1 #include <evt/GaisserHillas4Parameter.h>
2 #include <utl/Math.h>
3 #include <utl/MathConstants.h>
4 #include <utl/AugerUnits.h>
5 #include <utl/ErrorLogger.h>
6 #include <utl/LambertW.h>
7 #include <utl/Deprecator.h>
8 
9 #include <cmath>
10 #include <limits>
11 
12 using namespace utl;
13 using namespace std;
14 using namespace evt::gh;
15 
16 namespace evt {
17 
18  utl::TabulatedFunction GaisserHillas4Parameter::fRvsAsymTable;
19 
20  GaisserHillas4Parameter::GaisserHillas4Parameter(const EFunctionType functionType) :
21  fFunctionType(functionType),
22  fRhoShapePar1Par2(0)
23  {
24  for (int i = 0; i <= eLast; ++i) {
25  fShapePar[i] = 0;
26  fShapeParError[i] = 0;
27  fRhoNMaxShapePar[i] = 0;
28  fRhoXMaxShapePar[i] = 0;
29  }
30  }
31 
32  GaisserHillas4Parameter::GaisserHillas4Parameter(const double nMax, const double xMax,
33  const ShapeParameter par1,
34  const ShapeParameter par2,
35  const EFunctionType functionType) :
36  VGaisserHillasParameter(nMax, xMax),
37  fFunctionType(functionType),
38  fRhoShapePar1Par2(0)
39  {
40  for (int i = 0; i <= eLast; ++i) {
41  fShapeParError[i] = 0;
42  fRhoNMaxShapePar[i] = 0;
43  fRhoXMaxShapePar[i] = 0;
44  }
45  SetShapeParameter(par1.first, par1.second, 0);
46  SetShapeParameter(par2.first, par2.second, 0);
47  }
48 
49  double
50  GaisserHillas4Parameter::Eval(const double depth)
51  const
52  {
53 
54  if (fFunctionType == eUSP) {
55  // According to: Eq. (4), APP 34 (2011) 360
56  const double L = GetShapeParameter(eUSP_L);
57  const double R = GetShapeParameter(eUSP_R);
58  const double Y = (depth - fXMax)/L;
59 
60  double GH = 0;
61  if(std::abs(R) < 5.e-7)
62  GH = exp(-0.5*pow(Y, 2));
63 
64  if(R*Y > -1.){
65  const double p1 = log(1.+R*Y)-R*Y;
66  const double p2 = p1*pow(R,-2.);
67  GH = fNMax * exp(p2);
68  }
69 
70  double x0 = -(L/R) + fXMax;
71  if (depth <= x0)
72  return 0;
73  else
74  return GH;
75  }
76  else {
77  const double x0 = GetShapeParameter(eX0);
78  const double lam = GetShapeParameter(eLambda);
79 
80  if (depth <= x0)
81  return 0;
82  else {
83  const double tmp = fXMax - x0;
84  return fNMax * pow((depth - x0) / tmp, tmp/lam) *
85  exp((fXMax - depth) / lam);
86  }
87  }
88  }
89 
90  void
92  const
93  {
94  os << "GH function with 4 parameters" << '\n'
95  << " Nmax = " << fNMax << " +/- "<< fNMaxError << "\n"
96  << " Xmax = " << fXMax/g*cm2 << " +/- "<< fXMaxError/g*cm2
97  << " g/cm^2 \n";
98  for (int i = 0; i < eLast; ++i)
100  << fShapePar[i]/g*cm2 << " +/- "<< fShapeParError[i]/g*cm2;
101  os << endl;
102  }
103 
104  double
106  const
107  {
108  const double w = (fXMax - GetShapeParameter(eX0)) / GetShapeParameter(eLambda);
109 
110  if (w <= 0)
111  return 0;
112 
113  const double exponent = w + LogGamma(w+1);
114 
115  if (exponent < std::numeric_limits<double>::max_exponent10 * kLn10)
116  return fNMax * GetShapeParameter(eLambda) * pow(w, -w) * exp(exponent);
117  else
119  }
120 
121 
122  double
124  const
125  {
126  const double w0 = (fXMax - GetShapeParameter(eX0)) / GetShapeParameter(eLambda);
127 
128  const double wError =
131 
132  const double w1 = w0 + wError;
133  const double w2 = w0 - wError;
134 
135  if (w0 <= 0 || w2 <= 0)
137 
138  const double exponent0 = w0 * (1 - log(w0)) + LogGamma(w0 + 1);
139  const double exponent1 = w1 * (1 - log(w1)) + LogGamma(w1 + 1);
140  const double exponent2 = w2 * (1 - log(w2)) + LogGamma(w2 + 1);
141 
142  const double maxExp = std::numeric_limits<double>::max_exponent10 * kLn10;
143 
144  if (w0 > maxExp || w1 > maxExp || w2 > maxExp)
146 
147  const double gamma0 = exp(exponent0);
148  const double gamma1 = exp(exponent1);
149  const double gamma2 = exp(exponent2);
150 
151  const double f1 = 0.5 * (gamma1 - gamma2) / gamma0;
152  const double f2 = fNMaxError / fNMax;
153 
154  return sqrt(Sqr(f1) + Sqr(f2));
155  }
156 
157 
158  double
160  const
161  {
162 
163  switch (fFunctionType) {
164  case eClassic:
165  {
166  switch (par)
167  {
168  case eX0:
169  case eLambda:
170  return fShapePar[ExternalToInternal(par)];
171  case eFWHM:
172  return InverseRight(0.5) - InverseLeft(0.5);
173  case eAsym:
174  {
175  const double left = fXMax - InverseLeft(0.5);
176  const double right = InverseRight(0.5) - fXMax;
177  return left / (left + right);
178  }
179  case eUSP_L:
180  {
181  const double X0 = fShapePar[ExternalToInternal(eX0)];
182  const double lambda = fShapePar[ExternalToInternal(eLambda)];
183  const double X0prime = X0 - fXMax;
184  return sqrt(abs(X0prime*lambda));
185  }
186  case eUSP_R:
187  {
188  const double X0 = fShapePar[ExternalToInternal(eX0)];
189  const double lambda = fShapePar[ExternalToInternal(eLambda)];
190  const double X0prime = X0 - fXMax;
191  return sqrt(lambda/abs(X0prime));
192  }
193  }
194  break;
195  }
196  case eWidth:
197  {
198  switch (par)
199  {
200  case eX0:
201  {
202  const double asym = fShapePar[ExternalToInternal(eAsym)];
203  const double fwhm = fShapePar[ExternalToInternal(eFWHM)];
204  const double R = CalculateR(asym);
205  return fXMax - fwhm / R;
206  }
207  case eLambda:
208  {
209  const double asym = fShapePar[ExternalToInternal(eAsym)];
210  const double fwhm = fShapePar[ExternalToInternal(eFWHM)];
211  const double R = CalculateR(asym);
212  return fwhm * (log(1 - asym * R) + asym * R) / R / log(0.5);
213  }
214  case eFWHM:
215  case eAsym:
216  return fShapePar[ExternalToInternal(par)];
217  case eUSP_L:
218  {
219  const double asym = fShapePar[ExternalToInternal(eAsym)];
220  const double fwhm = fShapePar[ExternalToInternal(eFWHM)];
221  const double R = CalculateR(asym);
222  const double X0 = fXMax - fwhm / R;
223  const double lambda = fwhm * (log(1 - asym * R) + asym * R) / R / log(0.5);
224  const double X0prime = X0 - fXMax;
225  return sqrt(abs(X0prime*lambda));
226  }
227  case eUSP_R:
228  {
229  const double asym = fShapePar[ExternalToInternal(eAsym)];
230  const double fwhm = fShapePar[ExternalToInternal(eFWHM)];
231  const double R = CalculateR(asym);
232  const double X0 = fXMax - fwhm / R;
233  const double lambda = fwhm * (log(1 - asym * R) + asym * R) / R / log(0.5);
234  const double X0prime = X0 - fXMax;
235  return sqrt(lambda/abs(X0prime));
236  }
237  }
238  break;
239  }
240  case eUSP:
241  {
242  switch (par)
243  {
244  case eX0:
245  {
246  const double L = fShapePar[ExternalToInternal(eUSP_L)];
247  const double R = fShapePar[ExternalToInternal(eUSP_R)];
248  //L = sqrt(abs(X0prime*lambda));
249  //R = sqrt(lambda/abs(X0prime));
250  //L2 = X0prime * lambda;
251  //R2 = lambda / abs(X0prime);
252  //L2 = X0prime * R2 * abs(X0prime) = R2 * X0prime2
253  const double X0prime = -sqrt(L*L/(R*R));
254  //const double lambda = R*R * abs(X0prime);
255  return X0prime + fXMax;
256  }
257  case eLambda:
258  {
259  const double L = fShapePar[ExternalToInternal(eUSP_L)];
260  const double R = fShapePar[ExternalToInternal(eUSP_R)];
261  const double X0prime = -sqrt(L*L/(R*R));
262  const double lambda = R*R * abs(X0prime);
263  return lambda;
264  }
265  case eFWHM:
266  return InverseRight(0.5) - InverseLeft(0.5);
267  case eAsym:
268  {
269  const double left = fXMax - InverseLeft(0.5);
270  const double right = InverseRight(0.5) - fXMax;
271  return left / (left + right);
272  }
273  case eUSP_L:
274  case eUSP_R:
275  return fShapePar[ExternalToInternal(par)];
276  }
277  break;
278  }
279  }
280 
281  ostringstream errMsg;
282  errMsg << "no shape parameter available for "
283  << GetShapeParameterName(par)
284  << ", GH type " << GetFunctionTypeName(fFunctionType);
285  throw DoesNotComputeException(errMsg.str());
286 
287  }
288 
289 
290  double
292  const
293  {
294 
295  switch (fFunctionType) {
296  case eClassic:
297  {
298  switch (par)
299  {
300  case eX0:
301  case eLambda:
302  return fShapeParError[ExternalToInternal(par)];
303  case eFWHM:
304  case eAsym:
305  case eUSP_L:
306  case eUSP_R:
307  return 0; // error propagation not yet implemented
308  }
309  break;
310  }
311  case eWidth:
312  {
313  switch (par)
314  {
315  case eFWHM:
316  case eAsym:
317  return fShapeParError[ExternalToInternal(par)];
318  case eX0:
319  case eLambda:
320  case eUSP_L:
321  case eUSP_R:
322  return 0; // error propagation not yet implemented
323  }
324  break;
325  }
326  case eUSP:
327  {
328  switch (par)
329  {
330  case eUSP_L:
331  case eUSP_R:
332  return fShapeParError[ExternalToInternal(par)];
333  case eX0:
334  case eAsym:
335  case eLambda:
336  case eFWHM:
337  return 0; // error propagation not yet implemented
338  }
339  break;
340  }
341  }
342 
343  ostringstream errMsg;
344  errMsg << "no shape parameter available for "
345  << GetShapeParameterName(par)
346  << ", GH type " << GetFunctionTypeName(fFunctionType);
347  throw DoesNotComputeException(errMsg.str());
348 
349  }
350 
351  double
353  const
354  {
356  }
357 
358  double
360  const
361  {
363  }
364 
366  double
367  GaisserHillas4Parameter::Inverse(const double h, const int branch)
368  const
369  {
370  if (h <= 0 || h > 1) {
371  ostringstream errMsg;
372  errMsg << "Value "<< h <<" for fraction of NMax not in (0,1]";
373  throw OutOfBoundException(errMsg.str());
374  }
375 
376  const double x0 = GetShapeParameter(eX0);
377  const double lambda = GetShapeParameter(eLambda);
378  const double xmax = (fXMax - x0) / lambda;
379  const double z = - pow(h, 1/xmax) / kE;
380  const double xB = -xmax * (branch < 0 ? LambertW<-1>(z) :
381  LambertW<0>(z));
382  return x0 + lambda * xB ;
383  }
384 
385  double
387  const
388  {
389  return Inverse(h, 0);
390  }
391 
392  double
394  const
395  {
396  return Inverse(h, -1);
397  }
398 
399  inline
400  double
401  CalcFfromR(const double R)
402  {
403  // see Eq.(6) of width paper
404  return (exp(-R) * (1+R) - 1) / (R * (exp(-R) - 1));
405  }
406 
407  double
409  const
410  {
411 
412  const double asymMin = 0.01;
413  const double asymMax = 0.5;
414 
415  if (asym >= asymMin && asym <= asymMax) {
416 
417  // fill table for R vs. asym
418  if (!fRvsAsymTable.GetNPoints()) {
419  vector<double> rVal;
420  vector<double> fVal;
421 
422  // initial values at R = 0
423  double currR = 0;
424  double currAsym = 0.5;
425  rVal.push_back(currR);
426  fVal.push_back(currAsym);
427 
428  // fine binning for steep part
429  const double deltaRfine = 0.05;
430  while (currAsym > 0.4) {
431  currR += deltaRfine;
432  currAsym = CalcFfromR(currR);
433  rVal.push_back(currR);
434  fVal.push_back(currAsym);
435  }
436 
437  // coarse binning for flat part
438  const double deltaRCoarse = 1;
439  while (currAsym > asymMin) {
440  currR += deltaRCoarse;
441  currAsym = CalcFfromR(currR);
442  rVal.push_back(currR);
443  fVal.push_back(currAsym);
444  }
445  const int nPol = 2;
446  fRvsAsymTable = TabulatedFunction(fVal, rVal, nPol);
447  }
448 
449  return fRvsAsymTable.Y(asym);
450 
451  }
452  else {
453  ostringstream errMsg;
454  errMsg << "Asymmetry value " << asym <<" out of range [" << asymMin
455  << "," << asymMax << "]";
456  throw OutOfBoundException(errMsg.str());
457  }
458  }
459 
462  const
463  {
464  switch (fFunctionType) {
465  case eClassic: {
466  switch (par) {
467  case eX0:
468  return eFirst;
469  case eLambda:
470  return eLast;
471  default:
472  break;
473  }
474  break;
475  }
476  case eWidth:
477  {
478  switch (par) {
479  case eFWHM:
480  return eFirst;
481  case eAsym:
482  return eLast;
483  default:
484  break;
485  }
486  break;
487  }
488  case eUSP:
489  {
490  switch (par) {
491  case eUSP_L:
492  return eFirst;
493  case eUSP_R:
494  return eLast;
495  default:
496  break;
497  }
498  break;
499  }
500  }
501  ostringstream errMsg;
502  errMsg << "parameter " << gh::GetShapeParameterName(par)
503  << " is not a shape parameter of GH type "
505  throw DoesNotComputeException(errMsg.str());
506  }
507 
510  const
511  {
512  return InternalToExternal(fFunctionType, par);
513  }
514 
517  const EInternalShapeParameter par)
518  {
519  switch (type) {
520  case eClassic:
521  {
522  switch (par) {
523  case eFirst:
524  return eX0;
525  case eLast:
526  return eLambda;
527  }
528  break;
529  }
530  case eWidth:
531  {
532  switch (par) {
533  case eFirst:
534  return eFWHM;
535  case eLast:
536  return eAsym;
537  }
538  break;
539  }
540  case eUSP:
541  {
542  switch (par) {
543  case eFirst:
544  return eUSP_L;
545  case eLast:
546  return eUSP_R;
547  }
548  break;
549  }
550  }
551 
552  ostringstream errMsg;
553  errMsg << "no external shape parameter for par = " << par
554  << ", GH type " << GetFunctionTypeName(type);
555  throw DoesNotComputeException(errMsg.str());
556 
557  }
558 
559  void
561  const double rho)
562  {
564  }
565 
566  void
568  const double rho)
569  {
571  }
572 
573  void
575  const double value, const double error)
576  {
577  fShapePar[ExternalToInternal(par)] = value;
578  fShapeParError[ExternalToInternal(par)] = error;
579  }
580 
581 
582  bool
584  const
585  {
586  switch (fFunctionType) {
587  case eClassic:
588  {
589  switch (par)
590  {
591  case eX0:
592  case eLambda:
593  return true;
594  default:
595  return false;
596  }
597  break;
598  }
599  case eWidth:
600  {
601  switch (par)
602  {
603  case eFWHM:
604  case eAsym:
605  return true;
606  default:
607  return false;
608  }
609  break;
610  }
611  case eUSP:
612  {
613  switch (par)
614  {
615  case eUSP_L:
616  case eUSP_R:
617  return true;
618  default:
619  return false;
620  }
621  break;
622  }
623  }
624 
625  ostringstream errMsg;
626  errMsg << "no internal shape parameter defined for "
627  << GetShapeParameterName(par)
628  << ", GH type " << GetFunctionTypeName(fFunctionType);
629  throw DoesNotComputeException(errMsg.str());
630  }
631 
632  // -----------------------------------------------------------
633  // below this point only deprecated functions
634  double
636  const
637  {
638  Deprecator::GetInstance().Deprecated(
639  "evt::GaisserHillas4Parameter::GetXZero()",
640  "v2r9",
641  "GaisserHillas4Parameter::GetShapeParameter(gh::eX0)");
642  return GetShapeParameter(eX0);
643  }
644 
645  double
647  const
648  {
649  Deprecator::GetInstance().Deprecated(
650  "evt::GaisserHillas4Parameter::GetXZeroError()",
651  "v2r9",
652  "GaisserHillas4Parameter::GetShapeParameterError(gh::eX0)");
653  return GetShapeParameterError(eX0);
654  }
655 
656  double
658  const
659  {
660  Deprecator::GetInstance().Deprecated(
661  "evt::GaisserHillas4Parameter::GetLambda()",
662  "v2r9",
663  "GaisserHillas4Parameter::GetShapeParameter(gh::eLambda)");
664  return GetShapeParameter(eLambda);
665  }
666 
667  double
669  const
670  {
671  Deprecator::GetInstance().Deprecated(
672  "evt::GaisserHillas4Parameter::GetLambdaError()",
673  "v2r9",
674  "GaisserHillas4Parameter::GetShapeParameterError(gh::eLambda)");
676  }
677 
678  double
680  const
681  {
682  Deprecator::GetInstance().Deprecated(
683  "evt::GaisserHillas4Parameter::GetNMaxLambdaCorrelation()",
684  "v2r9",
685  "GaisserHillas4Parameter::GetCorrelationXMaxShapeParameter(gh::eLambda)");
687  }
688 
689  double
691  const
692  {
693  Deprecator::GetInstance().Deprecated(
694  "evt::GaisserHillas4Parameter::GetNMaxX0Correlation()",
695  "v2r9",
696  "GaisserHillas4Parameter::GetCorrelationXMaxShapeParameter(gh::eX0)");
698  }
699 
700  double
702  const
703  {
704  Deprecator::GetInstance().Deprecated(
705  "evt::GaisserHillas4Parameter::GetXMaxLambdaCorrelation()",
706  "v2r9",
707  "GaisserHillas4Parameter::GetCorrelationXMaxShapeParameter(gh::eLambda)");
709  }
710 
711  double
713  const
714  {
715  Deprecator::GetInstance().Deprecated(
716  "evt::GaisserHillas4Parameter::GetXMaxX0Correlation()",
717  "v2r9",
718  "GaisserHillas4Parameter::GetCorrelationXMaxShapeParameter(gh::eX0)");
720  }
721 
722  double
724  const
725  {
726  Deprecator::GetInstance().Deprecated(
727  "evt::GaisserHillas4Parameter::GetLambdaX0Correlation()",
728  "v2r9",
729  "GaisserHillas4Parameter::GetCorrelationShapeParameters()");
731  }
732 }
double GetShapeParameter(const gh::EShapeParameter par) const
access to all variants of shape parameters (see GaisserHillasTypes.h)
unsigned int GetNPoints() const
constexpr double kE
Definition: MathConstants.h:28
double GetCorrelationXMaxShapeParameter(const gh::EShapeParameter par) const
constexpr T Sqr(const T &x)
EInternalShapeParameter ExternalToInternal(const gh::EShapeParameter par) const
double GetCorrelationNMaxShapeParameter(const gh::EShapeParameter par) const
double GetIntegralError() const
return relative error of integral
double LambertW< 0 >(const double x)
Definition: LambertW.cc:559
Class to hold collection (x,y) points and provide interpolation between them.
double CalculateR(const double asym) const
std::pair< gh::EShapeParameter, double > ShapeParameter
void SetShapeParameter(const gh::EShapeParameter par, const double value, const double error)
Setters.
double pow(const double x, const unsigned int i)
double InverseLeft(const double h) const
return depth left of XMax for which GH = h*NMax
std::string GetFunctionTypeName(const EFunctionType type)
Exception for reporting variable out of valid range.
double InverseRight(const double h) const
return depth right of XMax for which GH = h*NMax
GaisserHillas4Parameter(const gh::EFunctionType functionType=gh::eClassic)
double CalcFfromR(const double R)
#define max(a, b)
double LogGamma(const double x)
double abs(const SVector< n, T > &v)
double LambertW(const double x)
constexpr double g
Definition: AugerUnits.h:200
bool IsInternal(const gh::EShapeParameter par) const
check if parameter &quot;par&quot; is one of the internal shape parameters
constexpr double kLn10
Definition: MathConstants.h:29
Base class for inconsistency/illogicality exceptions.
gh::EShapeParameter InternalToExternal(const EInternalShapeParameter) const
double Eval(const double depth) const
evaluate function a X = depth
double Inverse(const double h, const int branch) const
Inverse of GH function. branch = -1 is right of XMax, branch = 0 left of XMax.
Interface class for access to the Gaisser-Hillas parameters.
void SetCorrelationNMaxShapeParameter(const gh::EShapeParameter par, const double rho)
static utl::TabulatedFunction fRvsAsymTable
std::string GetShapeParameterName(const EShapeParameter par)
double GetShapeParameterError(const gh::EShapeParameter par) const
double GetIntegral() const
calculate integral
double Y(const double x) const
Get or interpolate the Y value that corresponds to parameter x.
void SetCorrelationXMaxShapeParameter(const gh::EShapeParameter par, const double rho)
void Dump(std::ostream &os=std::cout) const
dump the parameters
constexpr double cm2
Definition: AugerUnits.h:118

, generated on Tue Sep 26 2023.