UnivV2Rec.h
Go to the documentation of this file.
1 #ifndef __UnivV2Rec_h__
2 #define __UnivV2Rec_h__
3 
4 #include <cmath>
5 #include <float.h>
6 
7 #include <fwk/CentralConfig.h>
8 #include <utl/Branch.h>
9 #include <evt/Event.h>
10 #include <evt/ShowerRecData.h>
11 #include <evt/ShowerSRecData.h>
12 #include <evt/ShowerFRecData.h>
13 #include <evt/ShowerUnivRecData.h>
14 #include <evt/ShowerSimData.h>
15 #include <sevt/SEvent.h>
16 
17 #include <utl/Minou.h>
18 #include <utl/Math.h>
19 #include <utl/GeometryUtilities.h>
20 #include <utl/PhysicalFunctions.h>
21 #include <utl/NormalDistribution.h>
22 
23 // local
24 #include <src/UniversalityConfig.h>
25 #include <src/PowerConfig.h>
26 #include <src/GetSignal.h>
27 #include <src/Functions.h>
28 
29 namespace un2 {
30 
31  using namespace std;
32 
33  void SimpleReco(evt::Event& event);
34 
35 
36  class un2Detector {
37 
38  private:
39 
40  /* */
41 
42  public:
43 
44  un2Detector(const int id,
45  const sevt::Station& stat,
46  const string detType,
47  const double r,
48  const double az,
49  const double height,
50  const double pftimeres,
51  const double denseFlag) :
52  Id(id),
53  station(stat),
54  type(detType),
55  spRadius(r),
56  spAzimuth(az),
57  heightAboveSL(height),
58  pfTimeResidual(pftimeres),
59  isVirtual(denseFlag)
60  {
61 
62  //INFO(boost::format("%s r = %.2f m \t ψ = %.2f° \t h = %.1f m")%type %spRadius %Rad2Deg(spAzimuth) %heightAboveSL);
63 
64  };
65 
66  const unsigned int Id;
68 
69  const string type; // string
70  const double spRadius; // meter
71  const double spAzimuth; // rad
72  const double heightAboveSL; // meter
73  const double pfTimeResidual; // ns
74  const bool isVirtual;
75 
76  double mcSpRadius = 0;
77  double DX = 0;
78  double signalUnit = 0;
79  double avgAoP = 0;
80  double nsBin = 0;
81  double stationNSTime = 0;
82  unsigned int signalStartSlot = 0;
83  unsigned int signalStopSlot = 0;
84  double t40RelToStart = 0;
85  double Dt40 = 0;
86  vector<double> referenceDt40; // {value, uncertainty} in ns
87  vector<double> referenceDt0; // {value, uncertainty} in ns
88 
89  double weight = 1; /* artificially increases uncertainty, should be between 0 and 1 */
90 
91  double detBestFitXmax = 0;
92  double detBestFitRmu = 0;
93  double detBestFitT0 = 0;
94  double detBestFitN = 0;
95  double detChiSq = 0;
96 
97  double totalSignal;
100 
101  vector<double> integratedSignal = {0};
102  vector<double> integratedNormalizedSignal = {0};
103 
104  double
106  {
107  double unit = 0;
108 
109  if ("WCD" == type) {
110 
111  double tmp_AoP = 0;
112  double tmp_unit = 0;
113  int working_pmts = 0;
114  for (unsigned int i=1; i<4; ++i) {
115  try {
116  tmp_AoP += station.GetPMT(i).GetRecData().GetAreaOverPeak();
117  tmp_unit += station.GetPMT(i).GetRecData().GetVEMPeak() / station.GetPMT(i).GetRecData().GetVEMCharge();
118  working_pmts += 1;
119  } catch (utl::NonExistentComponentException& /*e*/) {
120  // WARNING(boost::format("No signal in one WCD PMT"));
121  continue;
122  }
123 
124  }
125 
126  unit = tmp_unit / working_pmts;
127  avgAoP = tmp_AoP / working_pmts;
128 
129  } else if ("SSD" == type) {
130 
131  if (station.GetScintillatorPMT().HasCalibData() &&
132  station.GetScintillatorPMT().HasRecData() &&
133  station.GetScintillator().HasRecData() &&
134  station.GetScintillator().HasMIPTrace()) {
135 
136  try {
137  unit = station.GetScintillatorPMT().GetRecData().GetVEMPeak() /
138  station.GetScintillatorPMT().GetRecData().GetVEMCharge();
139  } catch (utl::NonExistentComponentException& /*e*/) {
140  // WARNING(boost::format("No signal in SSD PMT"));
141  return 0;
142  }
143 
144  } else {
145  WARNING(boost::format("No SSD PMT data"));
146  return 0;
147  }
148 
149  }
150 
151  signalUnit = unit;
152 
153  return unit;
154  }
155 
156  const utl::TraceD&
158  {
159 
160  if ("WCD" == type) {
161 
162  return station.GetVEMTrace(traceType);
163 
164  }
165 
166  if ("SSD" == type) {
167 
168  return station.GetScintillator().GetMIPTrace(traceType);
169 
170  } else {
171 
172  WARNING(type);
173  WARNING("Detector type not found!");
174  return station.GetVEMTrace(traceType);
175 
176  }
177 
178  }
179 
180  bool
182  {
183 
184  if ("WCD" == type) {
185 
186  return station.HasVEMTrace(traceType);
187 
188  }
189 
190  if ("SSD" == type) {
191 
192  return station.GetScintillator().HasMIPTrace(traceType);
193 
194  } else {
195 
196  WARNING(type);
197  WARNING("Detector type not found!");
198  return station.HasVEMTrace(traceType);
199 
200  }
201 
202  }
203 
204  };
205 
206 
207 
208  class LDFFit : public utl::Minou::Base {
209 
210  private:
211 
212  vector<un2Detector> fun2Detectors;
213 
214  // meta parameters on event level
215  const utl::Branch topB = fwk::CentralConfig::GetInstance()->GetTopBranch("UniversalityFitterV2");
216  string fModel = topB.GetChild("HadronicInteractionModel").GetDataString();
217  double fXmax = 0;
218  double fLogE = 0;
219  double fTheta = 0;
220  bool fIsReal = false;
221  int fMonth = 3;
222 
223  public:
224 
225  LDFFit() :
226  //name start step low high fixed
227  Base({
228  {"Xmax", 780., .1, 600., 1200., true},
229  {"Rmu", 1., .01, 0., 3., true},
230  {"lgE", 19., .1, 18, 21., false}})
231 
232  {}
233 
234  void
235  AddDetectorData(un2Detector d)
236  {
237 
238  fun2Detectors.push_back(d);
239 
240  }
241 
242  void
243  AddMetaData(double avgXmax, double logE, double theta, bool sim, int month)
244  {
245 
246  fXmax = avgXmax;
247  fLogE = logE;
248  fTheta = theta;
249  fIsReal = !sim;
250  fMonth = month;
251 
252  }
253 
254  double
255  operator()(const vector<double>& p)
256  const
257  {
258 
259  double logLikelihood = 0;
260 
261  for(unsigned int d = 0; d < fun2Detectors.size(); ++d) {
262 
263  const bool useThrs = true;
264 
265  double ll = 0;
266 
267  const double predSignal = GetSignal(fModel, p[2], fTheta,
268  fun2Detectors[d].spRadius, fun2Detectors[d].spAzimuth, fun2Detectors[d].heightAboveSL,
269  p[0], p[1],
270  fun2Detectors[d].type, fMonth, fIsReal, useThrs)[0];
271 
272  //cout << fun2Detectors[d].type << " " << fun2Detectors[d].totalSignal << " " << predSignal << endl;
273 
274  if (fun2Detectors[d].totalSignal > 5) {
275 
276  ll += -utl::Sqr((fun2Detectors[d].totalSignal-predSignal)/fun2Detectors[d].uncertaintySignal);
277 
278  } else {
279 
280  ll += LogarithmOfTruncatedGaussianPDF(predSignal, fun2Detectors[d].totalSignal, fun2Detectors[d].uncertaintySignal);
281 
282  }
283 
284  logLikelihood += ll * fun2Detectors[d].weight;
285 
286  }
287 
288  return (!std::isnan(logLikelihood)) ? -logLikelihood : std::numeric_limits<double>::max();
289 
290  }
291 
292  };
293 
294 
296 
297  private:
298 
299  vector<vector<un2Detector>> fun2DetectorPairs;
300  vector<un2Detector> fun2Detectors;
301 
302  const utl::Branch topB = fwk::CentralConfig::GetInstance()->GetTopBranch("UniversalityFitterV2");
303  string fModel = topB.GetChild("HadronicInteractionModel").GetDataString();
304  double fXmax = 0;
305  double fLogE = 0;
306  double fTheta = 0;
307  bool fIsReal = false;
308  int fMonth = 3;
309 
310  public:
311 
313  //name start step low high fixed
314  Base({
315  {"Xmax", 780., .1, 600., 1200., false},
316  {"Rmu", 1.0, .01, 0., 3., false},
317  {"lgE", 19., .1, 18, 21., false}})
318 
319  {}
320 
321  void
322  AddDetector(un2Detector d)
323  {
324 
325  fun2Detectors.push_back(d);
326 
327  }
328 
329  int
330  NumPairs()
331  {
332 
333  return fun2DetectorPairs.size();
334 
335  }
336 
337  void
338  GeneratePairs()
339  {
340 
341  for (const auto& det : fun2Detectors) {
342 
343  if ("WCD" == det.type) {
344  continue;
345  }
346 
347  const unsigned int id = det.Id;
348 
349  for (const auto& matchDet : fun2Detectors) {
350 
351  if (id == matchDet.Id && "WCD" == matchDet.type) {
352 
353  fun2DetectorPairs.push_back({det, matchDet});
354 
355  }
356 
357  }
358 
359  }
360 
361  INFO(boost::format("Generated %i detector pairs for AugerPrime fit.") % fun2DetectorPairs.size());
362  for (const auto& dets : fun2DetectorPairs) {
363 
364  INFO(boost::format("%i (%i) %.2f MIP / %.2f VEM") % dets.at(0).Id % dets.at(1).Id % dets.at(0).totalSignal % dets.at(1).totalSignal);
365 
366  }
367 
368  }
369 
370  void
371  AddMetaData(double avgXmax, double logE, double theta, bool sim, int month)
372  {
373 
374  fXmax = avgXmax;
375  fLogE = logE;
376  fTheta = theta;
377  fIsReal = !sim;
378  fMonth = month;
379 
380  }
381 
382  double
383  operator()(const vector<double>& p)
384  const
385  {
386 
387  if (2>fun2DetectorPairs.size()) {
388  WARNING("Too few detector pairs generated for ratio fit!");
389  return 0;
390  }
391 
392  double logLikelihood = 0;
393  for(unsigned int d = 0; d < fun2DetectorPairs.size(); ++d) {
394 
395  const bool useThrs = true;
396  const auto& ssd = fun2DetectorPairs[d].at(0);
397  const auto& wcd = fun2DetectorPairs[d].at(1);
398  const double recSignalSSD = ssd.totalSignal;
399  const double recSignalWCD = wcd.totalSignal;
400 
401  const double predSignalSSD = GetSignal(fModel, p[2], fTheta,
402  ssd.spRadius, ssd.spAzimuth, ssd.heightAboveSL,
403  p[0], p[1],
404  ssd.type, fMonth, fIsReal, useThrs)[0];
405  const double predSignalWCD = GetSignal(fModel, p[2], fTheta,
406  wcd.spRadius, wcd.spAzimuth, wcd.heightAboveSL,
407  p[0], p[1],
408  wcd.type, fMonth, fIsReal, useThrs)[0];
409 
410  const double z = recSignalSSD / recSignalWCD;
411  const double zPred = predSignalSSD / predSignalWCD;
412  // const double uncRatio = ssd.uncertaintySignal/wcd.uncertaintySignal;
413 
414  // const double corr = 0.6; // rough estimate for signal residual correlation
415  //
416  // const double alpha = uncRatio * corr;
417  // const double beta = uncRatio * std::sqrt(1-utl::Sqr(corr));
418  //
419  // const double prob = 1./M_PI * beta/(utl::Sqr(z-alpha) + utl::Sqr(beta));
420 
421  // actually it is not perfectly gaussian, but deriving the PDF is quite tricky
422  // and it is almost gaussian
423  // sigma approximated from uncorrelated central normal ratio distribution
424  const double mu = z-zPred;
425  const double var = (utl::Sqr(ssd.uncertaintySignal/recSignalSSD) +
426  utl::Sqr(wcd.uncertaintySignal/recSignalWCD));
427  const double sigma = std::sqrt(var);
428  const double logprob = -0.5 * utl::Sqr(mu/sigma) - log(sigma*utl::kSqrt2Pi);
429  // cout << p[1] << "\t" << z << "\t" << prob << endl;
430 
431  logLikelihood += logprob;
432  //
433  // REALLY needed, unfortunately
434  if (predSignalWCD > 5) {
435 
436  logLikelihood += - 0.05 * utl::Sqr((predSignalWCD-recSignalWCD)/wcd.uncertaintySignal) -
437  log(wcd.uncertaintySignal*utl::kSqrt2Pi);
438  logLikelihood += - 0.05 * utl::Sqr((predSignalSSD-recSignalSSD)/ssd.uncertaintySignal) -
439  log(ssd.uncertaintySignal*utl::kSqrt2Pi);
440 
441  }
442 
443  }
444 
445  return (!std::isnan(logLikelihood)) ? -logLikelihood : std::numeric_limits<double>::max();
446 
447  }
448 
449  };
450 
451 
452  class RmuXmaxFit : public utl::Minou::Base {
453 
454  private:
455 
456  vector<un2Detector> fun2Detectors;
457 
458  // meta parameters on event level
459  const utl::Branch topB = fwk::CentralConfig::GetInstance()->GetTopBranch("UniversalityFitterV2");
460  string fModel = topB.GetChild("HadronicInteractionModel").GetDataString();
461  double fXmax = 0;
462  double fLogE = 0;
463  double fTheta = 0;
464  bool fIsReal = false;
465  int fMonth = 3;
466  bool fNorm = false;
467  double fPenalty = 0;
468 
469  public:
470 
472  //name start step low high fixed
473  Base({
474  {"Xmax", 780., .1, 600., 1200., false},
475  {"Rmu", 1.0, .01, 0., 3., false},
476  {"lgE", 19., .1, 18, 21., false}})
477 
478  {}
479 
480 
481  void
482  AddDetectorData(un2Detector d)
483  {
484 
485  fun2Detectors.push_back(d);
486 
487  }
488 
489 
490  void
491  AddMetaData(double avgXmax, double logE, double theta,
492  bool sim, int month, bool normalized, double penalty=0)
493  {
494 
495  fXmax = avgXmax;
496  fLogE = logE;
497  fTheta = theta;
498  fIsReal = !sim;
499  fMonth = month;
500  fNorm = normalized;
501  fPenalty = penalty;
502 
503  }
504 
505 
506  double
507  operator()(const vector<double>& p)
508  const
509  {
510 
511  double logLikelihood = 0;
512 
513  /* time information used here */
514  for (unsigned int d = 0; d < fun2Detectors.size(); ++d) {
515 
516  double ll = 0;
517  vector<double> timeVec = {};
518  vector<double> timeVecDet = {};
519 
520  // time shift allowed to counter trigger issues
521  const double t0 = p[3+d];
522  // use parametrized start time as a functino of Xmax
523  //const double t0 = GetTimeQuantile(fTheta, fun2Detectors[d].spRadius,
524  //fun2Detectors[d].spAzimuth, fun2Detectors[d].heightAboveSL,
525  //p[0], fun2Detectors[d].type, "t0", fMonth, fIsReal)[0].at(0);
526 
527  for (unsigned int t = 0; t < fun2Detectors[d].integratedSignal.size(); ++t) {
528  timeVec.push_back(t*fun2Detectors[d].nsBin);
529  timeVecDet.push_back(t*fun2Detectors[d].nsBin - t0);
530  }
531 
532  // allow for normalization
533  //const double norm = (fNorm) ? p[2+2*d+1] : 0;
534 
535  //const vector<double> st = GetIntegratedTotalSignal(timeVecDet, "EPOS-LHC", fLogE, fTheta,
536  const vector<double> st = GetIntegratedTotalSignalSum(timeVecDet, fModel, p[2], fTheta,
537  fun2Detectors[d].spRadius, fun2Detectors[d].spAzimuth, fun2Detectors[d].heightAboveSL,
538  p[0] /*xmax*/, p[1] /*rmu*/, fun2Detectors[d].type, fMonth, fIsReal, true,
539  //fun2Detectors[d].pfTimeResidual, fun2Detectors[d].nsBin, "cdf", 0 [>component integer<],
540  fun2Detectors[d].pfTimeResidual, fun2Detectors[d].nsBin,
541  fun2Detectors[d].integratedSignal.back());
542 
543  const vector<double> stunc = GetIntegratedTotalSignal(timeVec, fModel, p[2], fTheta,
544  fun2Detectors[d].spRadius, fun2Detectors[d].spAzimuth, fun2Detectors[d].heightAboveSL,
545  fXmax /*xmax*/, 1. /*rmu*/, fun2Detectors[d].type, fMonth, fIsReal, true,
546  fun2Detectors[d].pfTimeResidual, fun2Detectors[d].nsBin, "unc", 0,
547  fun2Detectors[d].totalSignal);
548 
549  for (unsigned int t = 0; t < timeVec.size(); ++t ) {
550 
551  //if (timeVec[t] < 50.) // first couple of bins are just too volatile, so skip 100 ns
552  //continue;
553 
554  // model is gaussian
555  ll += -1 * utl::Sqr((fun2Detectors[d].integratedSignal[t] - st[t]) /
556  (sqrt(utl::Sqr(stunc[t]) + fun2Detectors[d].totalSignal)) *
557  fun2Detectors[d].weight);
558  //cout << boost::format("ll: %.3f \t sig: %.1f \t n*st: %.1f \t unc: %.1f\n")
559  // %ll %fun2Detectors[d].integratedSignal[t] %(norm * st[t]) %stunc[t];
560 
561  }
562 
563  if (!std::isnan(ll)) {
564 
565  // check for -nan cases
566  logLikelihood += ll;
567 
568  } else {
569 
570  logLikelihood += -1e5;
571 
572  }
573 
574  // cout << p[0] << "\t"<< ll << "\t" << d << "/" << fun2Detectors.size() << endl;
575 
576  }
577 
578  /* signal information used here */
579  for(unsigned int d = 0; d < fun2Detectors.size(); ++d) {
580 
581  double ll = 0;
582 
583  const double predSignal = GetSignal(fModel, p[2], fTheta,
584  fun2Detectors[d].spRadius, fun2Detectors[d].spAzimuth, fun2Detectors[d].heightAboveSL,
585  p[0], p[1],
586  fun2Detectors[d].type, fMonth, fIsReal, true)[0];
587 
588  if (fun2Detectors[d].totalSignal > 5) {
589 
590  ll += -utl::Sqr((fun2Detectors[d].totalSignal-predSignal)/fun2Detectors[d].uncertaintySignal);
591 
592  } else {
593 
594  ll += LogarithmOfTruncatedGaussianPDF(predSignal, fun2Detectors[d].totalSignal, fun2Detectors[d].uncertaintySignal);
595 
596  }
597 
598  /* correlation information is used here */
599  // Rµ Xmax correlation penalty
600  // CAVEAT:
601  // this penalty constrains forces the reconstructed Xmax value to follow the implemented
602  // distribution. this is good if you want to constrain your fit but might be misleading
603  // if you want to check what the reconstruction is doing with the trace shape information of the
604  // stations only.
605  // for real data the Xmax/Rmu correlation is different than from simulation, therefore
606  // this information must be parsed here, if the penalty is on. currently this is done using
607  // the calibrated lnRµ0 estimated from EPOS-LHC protons.
608  // Remove this for photon searches!
609  if (!std::isnan(ll)) {
610 
611  const double penaltyContribution = log(XmaxDistribution(p[1], p[0], p[2], fIsReal));
612  logLikelihood += fPenalty * penaltyContribution * 50 * pow(10, fLogE-19);
613  logLikelihood += ll * fun2Detectors[d].weight * 0.1;
614 
615  } else {
616 
617  logLikelihood += -1e5;
618 
619  }
620 
621  // if you change anything at the Xmax/Rmu correlation you have to adjust the multiplicator
622  // wrt to the station likelihood. this is a magic number, unfortunately! the exact
623  // value however does not change the Xmax reconstruction much.
624  // check output for estimating fudge factor
625  //cout << p[0] << " " << p[1] << "\t"<< logLikelihood << "\t" << penaltyContribution << "\tratio:" <<
626  //logLikelihood / penaltyContribution / fun2Detectors.size() << endl;
627  }
628 
629  // check if nan, if so return maximum float number
630  return (!std::isnan(logLikelihood)) ? -logLikelihood : std::numeric_limits<double>::max();
631 
632  }
633 
634  };
635 
636 };
637 
638 #endif
constexpr double kSqrt2Pi
Definition: MathConstants.h:32
bool HasTrace(sevt::StationConstants::SignalComponent traceType)
Definition: UnivV2Rec.h:181
constexpr T Sqr(const T &x)
const double spAzimuth
Definition: UnivV2Rec.h:71
total (shower and background)
double LogarithmOfTruncatedGaussianPDF(const double x, const double mu, const double sigma)
Definition: Functions.cc:213
un2Detector(const int id, const sevt::Station &stat, const string detType, const double r, const double az, const double height, const double pftimeres, const double denseFlag)
Definition: UnivV2Rec.h:44
const sevt::Station & station
Definition: UnivV2Rec.h:67
const double pfTimeResidual
Definition: UnivV2Rec.h:73
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
vector< double > referenceDt0
Definition: UnivV2Rec.h:87
Base class for exceptions trying to access non-existing components.
vector< un2Detector > fun2Detectors
Definition: UnivV2Rec.h:456
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
double pow(const double x, const unsigned int i)
const string type
Definition: UnivV2Rec.h:69
#define max(a, b)
Class representing a document branch.
Definition: Branch.h:107
double totalSignal
Definition: UnivV2Rec.h:97
class to hold data at Station level
double uncertaintySignal
Definition: UnivV2Rec.h:99
double referenceSignal
Definition: UnivV2Rec.h:98
double XmaxDistribution(const double Rmu, const double Xmax, const double lgE, const bool realEvent)
Definition: Functions.cc:483
const bool isVirtual
Definition: UnivV2Rec.h:74
vector< double > GetSignal(string model, double lgE, double zenith, double r, double psi, double height, double Xmax, double Rmu, string detector, int month, bool realAtmosphere, bool useThreshold)
Definition: GetSignal.cc:24
const double spRadius
Definition: UnivV2Rec.h:70
vector< vector< un2Detector > > fun2DetectorPairs
Definition: UnivV2Rec.h:299
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
const double unit[npar]
Definition: UnivRec.h:76
std::string GetDataString() const
function to get the data inside an element as one big string
Definition: Branch.cc:390
const utl::TraceD & GetTrace(sevt::StationConstants::SignalComponent traceType=sevt::StationConstants::eTotal)
Definition: UnivV2Rec.h:157
const double heightAboveSL
Definition: UnivV2Rec.h:72
static CentralConfig * GetInstance()
Use this the first time you get an instance of central configuration.
vector< double > GetIntegratedTotalSignalSum(vector< double > t, string model, double lgE, double zenith, double r, double psi, double height, double Xmax, double Rmu, string detector, int month, bool realAtmosphere, bool useThreshold, double planeFrontTimeResidual, double nsBin, double normalized)
Definition: GetSignal.cc:476
vector< double > GetIntegratedTotalSignal(vector< double > t, string model, double lgE, double zenith, double r, double psi, double height, double Xmax, double Rmu, string detector, int month, bool realAtmosphere, bool useThreshold, double planeFrontTimeResidual, double nsBin, string returnValue, int component, double normalized)
Definition: GetSignal.cc:393
vector< un2Detector > fun2Detectors
Definition: UnivV2Rec.h:300
void SimpleReco(evt::Event &event)
Definition: UnivV2Rec.cc:48
vector< un2Detector > fun2Detectors
Definition: UnivV2Rec.h:212
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)
vector< double > referenceDt40
Definition: UnivV2Rec.h:86
double CalcUnit()
Definition: UnivV2Rec.h:105

, generated on Tue Sep 26 2023.