SdSimMuonNumberFitter.cc
Go to the documentation of this file.
2 
3 #include <fwk/LocalCoordinateSystem.h>
4 #include <fwk/CentralConfig.h>
5 
6 #include <utl/ErrorLogger.h>
7 #include <utl/MathConstants.h>
8 #include <utl/PhysicalConstants.h>
9 #include <utl/AugerUnits.h>
10 #include <utl/UTMPoint.h>
11 #include <utl/Reader.h>
12 #include <utl/Particle.h>
13 #include <utl/TimeStamp.h>
14 #include <utl/TimeInterval.h>
15 
16 #include <sdet/MuonProfile.h>
17 #include <utl/HASUtilities.h>
18 
19 #include <det/Detector.h>
20 
21 #include <sdet/SDetector.h>
22 
23 #include <evt/Event.h>
24 #include <evt/ShowerSimData.h>
25 #include <evt/ShowerRecData.h>
26 #include <evt/ShowerSRecData.h>
27 
28 #include <sevt/Header.h>
29 #include <sevt/SEvent.h>
30 #include <sevt/Station.h>
31 #include <sevt/StationSimData.h>
32 #include <sevt/StationRecData.h>
33 
34 #include <sstream>
35 #include <fstream>
36 #include <iomanip>
37 #include <iostream>
38 
39 #include <TFile.h>
40 #include <TMath.h>
41 #include <TH2D.h>
42 #include <TMinuit.h>
43 #include <TCanvas.h>
44 #include <TVirtualPad.h>
45 
46 #include <boost/tuple/tuple.hpp>
47 
48 using namespace SdSimMuonNumberFitterNS;
49 using namespace fwk;
50 using namespace utl;
51 using namespace HASUtilities;
52 using namespace sdet;
53 using namespace evt;
54 using namespace sevt;
55 using namespace std;
56 
57 
58 typedef boost::tuple<double, double> Tuple2D;
59 
60 //ofstream gDebugLog("debug.log");
61 
62 static int kHASRecoStatus = 10;
63 
64 MuonProfile* fgMuonProfile = nullptr;
65 
66 // square of the perpendicular distance from the axis
67 inline
68 double
69 RPerp2(const Vector& axis, const Vector& station)
70 {
71  const double scal = axis*station;
72  return station*station - scal*scal;
73 }
74 
75 
76 // perpendicular distance from the axis
77 inline
78 double
79 RPerp(const Vector& axis, const Vector& station)
80 {
81  return sqrt(RPerp2(axis, station));
82 }
83 
84 
85 template<typename G>
86 inline
87 string
88 ToString(const G& g, const CoordinateSystemPtr cs)
89 {
90  ostringstream os;
91  os << '('
92  << g.GetX(cs)/meter << ", "
93  << g.GetY(cs)/meter << ", "
94  << g.GetZ(cs)/meter << ") [m]";
95  return os.str();
96 }
97 
98 
99 inline
101 GetShowerCoordinateSystem(const double theta, const double phi,
102  const Point& core)
103 {
104  return CoordinateSystem::RotationY(theta,
105  CoordinateSystem::RotationZ(phi,
106  LocalCoordinateSystem::Create(core)));
107 }
108 
109 
110 // project point into core plane in the direction of the shower origin
111 inline
112 Tuple2D
113 ProjectIntoCorePlane(const Point& pos, const Point& showerOrigin, const CoordinateSystemPtr& coreCS)
114 {
115  const double dz = pos.GetZ(coreCS);
116  const Vector stationToOrigin = showerOrigin-pos;
117  const Point corePlanePos = stationToOrigin/stationToOrigin.GetZ(coreCS)*dz + pos;
118  return Tuple2D(corePlanePos.GetX(coreCS),corePlanePos.GetY(coreCS));
119 }
120 
121 
122 inline
123 Tuple2D
124 ProjectIntoCorePlane2(const Point& pos, const Point& showerOrigin, const CoordinateSystemPtr& coreCS)
125 {
126  const Vector axis = showerOrigin - Point(0,0,0, coreCS);
127  const double dz = pos.GetZ(coreCS);
128  const Point pos2 = pos - axis/axis.GetZ(coreCS)*dz;
129  return Tuple2D(pos2.GetX(coreCS), pos2.GetY(coreCS));
130 }
131 
132 
133 // get local shower inclination at position "pos"
134 inline
135 double
136 LocalCosTheta(const Point& pos, const Point& showerOrigin)
137 {
138  const Vector stationToOrigin = showerOrigin - pos;
139  return stationToOrigin.GetCosTheta(LocalCoordinateSystem::Create(pos));
140 }
141 
142 
143 void
144 Likelihood::AddStation(const int id, const Point& pos, const Point& showerOrigin, const CoordinateSystemPtr& coreCS, const unsigned int nmuon)
145 {
146  // projection into flat muon density plane along shower axis
147  // axis points upwards to the shower "source", we safely assume that axis is normalised
148  Tuple2D sPosProjXY = ProjectIntoCorePlane(pos, showerOrigin, coreCS);
149  const double sTheta = acos(LocalCosTheta(pos, showerOrigin));
150  fStationList.push_back(InternalStationData(id, sPosProjXY.get<0>(), sPosProjXY.get<1>(), sTheta,nmuon));
151 }
152 
153 
154 void
155 Likelihood::MinuitFnc(int& nPar, double* const grad, double& value, double* const par, const int flag)
156 {
157  // p[0] N19
158  // p[1] x_core
159  // p[2] y_core
160 
161  if (par[0] <= 0) {
162  value = DBL_MAX;
163  return;
164  }
165 
166  double logLikelihood = 0;
167  for (InternalStationList::const_iterator sIt = fStationList.begin();
168  sIt != fStationList.end(); ++sIt) {
169  const double& x = sIt->fX;
170  const double& y = sIt->fY;
171  //const double& th = sIt->fTheta;
172  const int& nmu = sIt->fNMuon;
173  double nmuExpected = 0;
174  try {
175  nmuExpected = par[0]
176  * fgMuonProfile->NMuon(x - par[1], y - par[2], fTheta, fPhi, 10*EeV);
177  } catch (OutOfBoundException& e) {
178  nmuExpected = 1e-9;
179  }
180 
181  double p = TMath::Poisson(nmu, nmuExpected);
182  if (p > 0)
183  logLikelihood += log(p);
184  else
185  logLikelihood += -DBL_MAX_EXP;
186  }
187 
188  if (logLikelihood < -DBL_MAX) {
189  ERROR("logLikelihood = -infinity!");
190  value = DBL_MAX;
191  return;
192  }
193 
194  if (logLikelihood != logLikelihood) {
195  ERROR("Likelihood = nan!");
196  value = DBL_MAX;
197  return;
198  }
199 
200  value = -logLikelihood;
201 }
202 
203 
205 
206 
208 { }
209 
210 
212 {
213  delete fgMuonProfile;
214 }
215 
216 
219 {
220  CentralConfig* const cc = CentralConfig::GetInstance();
221 
222  Branch topB = cc->GetTopBranch("SdSimMuonNumberFitter");
223 
224  topB.GetChild("Verbosity").GetData(fVerbosity);
225 
226  // muon profiles are only defined up to about 4000 m distance
227  topB.GetChild("MaxDistanceZeroSignalStations").GetData(fSilentRadius);
228 
229  string muonProfile;
230  topB.GetChild("MuonProfile").GetData(muonProfile);
231  Branch muonProfileBranch = cc->GetTopBranch("MuonProfile").GetChild(muonProfile.c_str());
232  fgMuonProfile = new sdet::MuonProfile(muonProfileBranch);
233 
234  topB.GetChild("EnergyConstant").GetData(fEnergyConstant);
235 
236  topB.GetChild("Gamma").GetData(fGamma);
237 
238  fFixedCore = bool(topB.GetChild("FixedCore"));
239 
240  if (fVerbosity >= ErrorLogger::eInfo) {
241  ostringstream msg;
242  msg << "\nParameters:\n"
243  << " Verbosity : " << fVerbosity << "\n"
244  << " MaxDistanceZeroSignalStations : " << fSilentRadius << " m\n"
245  << " MuonProfile : " << muonProfileBranch.GetName()
246  << " Theta limits [" << fgMuonProfile->GetThetaMin()/degree << " Deg, "
247  << fgMuonProfile->GetThetaMax()/degree << " Deg]" << "\n"
248  << " EnergyConstant(EnergyConversion): " << fEnergyConstant << " eV\n"
249  << " Gamma (EnergyConversion): " << fGamma << "\n"
250  << " Fixed core : " << (fFixedCore ? "yes\n" : "no\n");
251  INFO(msg);
252  }
253 
254  return eSuccess;
255 }
256 
257 
260 {
261  // nothing to do if there is no SimShower or no SEvent
262  if (!event.HasSimShower())
263  return eContinueLoop;
264  if (!event.HasSEvent())
265  return eContinueLoop;
266 
267  sevt::SEvent& sEvent = event.GetSEvent();
268  const evt::ShowerSimData& showerSimData = event.GetSimShower();
269  const sdet::SDetector& sDetector = det::Detector::GetInstance().GetSDetector();
270  if (!event.HasRecShower())
271  event.MakeRecShower();
272  if (!event.GetRecShower().HasSRecShower())
273  event.GetRecShower().MakeSRecShower();
274  ShowerSRecData& showersrec = event.GetRecShower().GetSRecShower();
275 
276  // Get true shower core, axis, core time
277  const Point& simCore = showerSimData.GetPosition();
278  const TimeStamp& simTime = showerSimData.GetTimeStamp();
279  const Vector& showerAxis = -showerSimData.GetDirection();
280  fSimCoreCS = showerSimData.GetLocalCoordinateSystem();
281 
282  const double energyMC = showerSimData.GetEnergy();
283  const double thetaMC = showerSimData.GetZenith();
284  const double phiMC = showerSimData.GetAzimuth();
285 
286  // Build up station lists
287  vector<StationData> candidateList;
288  vector<StationData> silentList;
289  for (SEvent::ConstStationIterator sIt = sEvent.StationsBegin();
290  sIt != sEvent.StationsEnd(); ++sIt) {
291  const sdet::Station& dStation = sDetector.GetStation(*sIt);
292  const sevt::StationSimData& sSim = sIt->GetSimData();
293 
294  StationData sd;
295  sd.fId = sIt->GetId();
296  sd.fPos = dStation.GetPosition();
297  sd.fNMuon = 0;
298  sd.fTime = TimeStamp(0,0);
299 
300  bool noParticleData = true;
302  it != sSim.ParticlesEnd(); ++it) {
303  noParticleData = false;
304  if (abs(it->GetType()) == Particle::eMuon)
305  ++sd.fNMuon;
306  const TimeStamp pTime = simTime + it->GetTime();
307  if (!sd.fTime)
308  sd.fTime = pTime;
309  if (pTime < sd.fTime)
310  sd.fTime = pTime;
311  }
312  if (noParticleData && sIt->IsCandidate() && sIt->HasRecData()) {
313  const sevt::StationRecData& sRec = sIt->GetRecData();
314  // if we don't have the particle information, assume that the muon number is encoded in the tank signal value
315  sd.fNMuon = (unsigned int)(sRec.GetTotalSignal());
316  sd.fTime = sRec.GetSignalStartTime();
317  }
318 
319  if (sd.fNMuon > 0)
320  candidateList.push_back(sd);
321  else if (RPerp(showerAxis, sd.fPos - simCore) < fSilentRadius)
322  silentList.push_back(sd);
323  }
324 
325  if (fVerbosity > ErrorLogger::eDebug) {
326  for (unsigned int i = 0; i < candidateList.size(); ++i) {
327  const StationData& sd = candidateList[i];
328  cerr << "Station " << sd.fId << ": " << sd.fNMuon << endl;
329  }
330  }
331 
332  if(fVerbosity > ErrorLogger::eInfo) {
333  ostringstream msg;
334  msg << "\tSEvent Id = " << sEvent.GetHeader().GetId() << "\n"
335  << "\tThetaMC " << showerSimData.GetZenith()/deg << " [deg]" << "\n"
336  << "\t# total number of stations = " << sEvent.GetNumberOfStations() << "\n"
337  << "\t# number of candidate stations = " << candidateList.size() << "\n"
338  << "\t# number of silent stations = " << silentList.size() << endl;
339  INFO(msg);
340  }
341 
342  // not worth it
343  if (candidateList.size() < 3) {
344  INFO("Not enough stations.");
345  showersrec.SetS1000(0, 0);
346  return eSuccess;
347  }
348 
349  const Point barycenter = FindMuonDensityBaryCenter(candidateList);
350 
351  // once a barycenter, create: local coordinate system, calculate shower origin, barytime
352  const CoordinateSystemPtr baryCS = LocalCoordinateSystem::Create(barycenter);
353  Point showerOrigin = barycenter + showerAxis*AverageCurvatureRadius(thetaMC);
354  const TimeStamp coreTime = simTime -
355  TimeInterval(showerAxis*(barycenter - simCore)/kSpeedOfLight);
356 
357  for (vector<StationData>::const_iterator sIt = candidateList.begin();
358  sIt != candidateList.end(); ++sIt) {
359  sevt::Station& station = sEvent.GetStation(sIt->fId);
360  if (!station.HasRecData())
361  station.MakeRecData();
362  StationRecData& sRec = station.GetRecData();
363 
364  const double signal = sIt->fNMuon;
365 
366  const TimeStamp sTime = sIt->fTime + (coreTime - simTime);
367 
368  sRec.SetTotalSignal(signal, sqrt(signal));
369  sRec.SetSignalStartTime(sTime);
370  sRec.SetT50(0,0);
371  }
372 
373  // warn, if event is out of range
374  const bool notInMuonProfileRange =
375  thetaMC < fgMuonProfile->GetThetaMin() || fgMuonProfile->GetThetaMax() < thetaMC;
376 
377  if (notInMuonProfileRange) {
378  if (fVerbosity > ErrorLogger::eInfo) {
379  ostringstream msg;
380  msg << "Theta = " << thetaMC/degree << " Deg was not in valid range of\n ";
381  if (notInMuonProfileRange)
382  msg << " MuonProfile";
383  msg << "\n";
384  INFO(msg);
385  }
386  }
387 
388  // energy reco
389  Point core;
390  Vector coreErr;
391  double n19 = 0;
392  double n19Err = 0;
393  double logLikelihoodMin = 0;
394  gLikelihood.Clear();
395  for (vector<StationData>::const_iterator sIt=candidateList.begin();
396  sIt != candidateList.end(); ++sIt) {
397  gLikelihood.AddStation(sIt->fId, sIt->fPos, showerOrigin, baryCS, sIt->fNMuon);
398  }
399  for (vector<StationData>::const_iterator sIt = silentList.begin();
400  sIt != silentList.end(); ++sIt) {
401  gLikelihood.AddStation(sIt->fId, sIt->fPos, showerOrigin, baryCS, 0);
402  }
403  gLikelihood.SetTheta(thetaMC);
404  gLikelihood.SetPhi(phiMC);
405 
406  n19 = 1;
407  bool success = EnergyFit(baryCS, core, coreErr, n19, n19Err, logLikelihoodMin, true);
408  if (!success) {
409  ERROR("Failed N19 estimate fit (fixed core to barycenter)");
410  showersrec.SetS1000(0, 0);
411  return eSuccess;
412  }
413  const double n19estimate = n19;
414 
415  if (200 <= fVerbosity) { // draw loglikelihood debug stuff
416  char buf[1024];
417  int phii = int(phiMC/degree);
418  if (phii < 0)
419  phii += 360;
420  sprintf(buf, "lh_map_%09i_%i_%i.root", sEvent.GetHeader().GetId(), int(thetaMC/degree), phii);
421  TFile f(buf, "RECREATE");
422  TCanvas* const c = new TCanvas;
423  c->Divide(1, 2);
424  c->cd(1);
425  DrawMuonDensity(gPad, n19estimate, thetaMC, phiMC, "est");
426  c->cd(2);
427  DrawLogLikelihood(gPad, n19estimate, "est");
428  c->Write();
429  f.Close();
430  delete c;
431  }
432 
433  success = EnergyFit(baryCS, core, coreErr, n19, n19Err, logLikelihoodMin, false);
434  if (!success) {
435  showersrec.SetS1000(n19estimate, 0);
436  ERROR("Failed N19 + core fit");
437 
438  if (100 <= fVerbosity && fVerbosity < 200) { // draw loglikelihood debug stuff
439  char buf[1024];
440  int phii = int(phiMC/degree);
441  if (phii < 0)
442  phii += 360;
443  sprintf(buf, "lh_map_%09i_%i_%i.root", sEvent.GetHeader().GetId(), int(thetaMC/degree), phii);
444  TFile f(buf, "RECREATE");
445  TCanvas* const c = new TCanvas;
446  c->Divide(1, 2);
447  c->cd(1);
448  DrawMuonDensity(gPad, n19estimate, thetaMC, phiMC, "est");
449  c->cd(2);
450  DrawLogLikelihood(gPad, n19estimate, "est");
451  c->Write();
452  f.Close();
453  delete c;
454  }
455 
456  return eSuccess;
457  }
458  showerOrigin = core + showerAxis*AverageCurvatureRadius(thetaMC);
459 
460  // Convert N19 to energy
461  const double Energy = fEnergyConstant * pow(n19,fGamma);
462  const double EnergyError = n19Err * fEnergyConstant*fGamma*pow(n19, fGamma-1);
463 
464  const double diffToMC = Energy/energyMC - 1;
465  const double diffToMCSigma = (Energy - energyMC) / EnergyError;
466 
467  if (fVerbosity > ErrorLogger::eInfo) {
468  ostringstream msg;
469  msg << "Result:\n"
470  << "\tEnergy - XML Calibration : " << Energy/EeV << " +/- " << EnergyError/EeV
471  << " [EeV]\n"
472  << "\tMonte-Carlo Energy : " << energyMC/EeV << " [EeV]"
473  << " ( " << setprecision(3) << diffToMC*100.
474  << " % | " << setprecision(3) << diffToMCSigma << " std.dev. )" << endl;
475  INFO(msg);
476  }
477 
478  // fill SRecShower
479  if (!event.HasRecShower())
480  event.MakeRecShower();
481  if (!event.GetRecShower().HasSRecShower())
482  event.GetRecShower().MakeSRecShower();
483 
484  const CoordinateSystemPtr coreCS = LocalCoordinateSystem::Create(core);
485  const CoordinateSystemPtr showerPlaneCS = GetShowerCoordinateSystem(thetaMC, phiMC, core);
486 
487  double chi2 = 0;
488  unsigned int ndof = 0;
489  for (vector<StationData>::const_iterator sIt = candidateList.begin();
490  sIt != candidateList.end(); ++sIt) {
491  const Point& sPos = sIt->fPos;
492 
493  const Tuple2D sPosProjXY = ProjectIntoCorePlane(sPos, showerOrigin, coreCS);
494 
495  double muons = 0;
496  try {
497  muons = n19
498  * fgMuonProfile->NMuon(sPosProjXY.get<0>(),
499  sPosProjXY.get<1>(), thetaMC, phiMC, 10*EeV);
500  } catch (OutOfBoundException& e) {
501  continue;
502  }
503 
504  const double signalPred = muons;
505  sevt::Station& station = sEvent.GetStation(sIt->fId);
506  StationRecData& sRec = station.GetRecData();
507 
508  const double signal = sIt->fNMuon;
509  const double sigma = sqrt(signalPred);
510  const double res = (signal - signalPred) / sigma;
511 
512  const double rho = RPerp(showerAxis, sPos - core);
513  const double drho = 0; // TODO calculate this, see LDFFinder
514 
515  chi2 += (res*res) / signalPred; // sigma^2 = mean for poisson statistics
516  ++ndof;
517 
518  sRec.SetTotalSignal(signal, sigma);
519  sRec.SetAzimuthShowerPlane(sPos.GetPhi(showerPlaneCS));
520  sRec.SetLDFResidual((signal - signalPred)/sigma);
521  sRec.SetSPDistance(rho, drho);
522  }
523 
524  showersrec.SetBarycenter(barycenter);
525  showersrec.SetCorePosition(core);
526  showersrec.SetCoreError(coreErr);
527  showersrec.SetCoreTime(coreTime, TimeInterval(0));
528  showersrec.SetAxis(showerAxis);
529  showersrec.SetCurvature(0, 0);
530  showersrec.SetEnergy(Energy, EnergyError);
531  showersrec.SetS1000(n19, n19Err);
532  showersrec.SetLDFChi2(chi2, ndof);
533  showersrec.SetLDFLikelihood(logLikelihoodMin);
534  // LDFRecStatus variable > 10 for HAS
535  showersrec.SetLDFRecStage(ShowerSRecData::kLDF + kHASRecoStatus);
536 
537  return eSuccess;
538 }
539 
540 
543 {
544  return eSuccess;
545 }
546 
547 
549 SdSimMuonNumberFitter::FindMuonDensityBaryCenter(const vector<StationData>& stationList)
550  const
551 {
552  const det::Detector& detector = det::Detector::GetInstance();
553 
554  // calculate barycenter and bary-time
555  const CoordinateSystemPtr siteCS = detector.GetSiteCoordinateSystem();
556 
557  // the absolute points in time and space
558  const Point siteOrigin(0,0,0, siteCS);
559 
560  // weighted sums
561  Vector barySum(0,0,0, siteCS);
562  double weightSum = 0;
563  int nStations = 0;
564  for (vector<StationData>::const_iterator it = stationList.begin();
565  it != stationList.end(); ++it) {
566  const StationData& sd = *it;
567  const double weight = sqrt(double(sd.fNMuon));
568  weightSum += weight;
569  barySum += weight * (sd.fPos - siteOrigin);
570  ++nStations;
571  }
572 
573  if (!weightSum) {
574  ERROR("sum of weights = 0");
575  return Point();
576  }
577 
578  barySum /= weightSum;
579  Point barycenter = siteOrigin + barySum;
580 
581  ostringstream msg;
582  msg << "\nbarycenter = " << ToString(barycenter, fSimCoreCS) << " (showerGroundCS)" << "\n";
583  INFO(msg);
584 
585  return barycenter;
586 }
587 
588 
589 void
590 SdSimMuonNumberFitter::N19FitFnc(int& nPar, double* const grad, double& value, double* const par, const int flag)
591 {
592  gLikelihood.MinuitFnc(nPar, grad, value, par, flag);
593 }
594 
595 
596 bool
598  Point& core, Vector& coreErr, double& n19, double& n19Err,
599  double& logLikelihoodMin, const bool fixedCore)
600  const
601 {
602  TMinuit minuit(3);
603 
604  bool badFit = false;
605 
606  int errFlag = 0;
607  double argList[10];
608  argList[0] = -1;
609 
610  minuit.mnexcm("SET PRINTOUT", argList, 1, errFlag);
611  minuit.mnexcm("SET NOWARNINGS", argList, 0, errFlag);
612  minuit.SetPrintLevel(-1);
613 
614  minuit.SetFCN(SdSimMuonNumberFitter::N19FitFnc);
615  minuit.mnparm(0, "N19" , n19, 0.2, 0.0, 0.0, errFlag);
616  minuit.mnparm(1, "xCore", 0.0, 100.0*meter, 0.0, 0.0, errFlag);
617  minuit.mnparm(2, "yCore", 0.0, 100.0*meter, 0.0, 0.0, errFlag);
618 
619  //Change in FCN of one-standard-deviation error
620  argList[0] = 0.5;
621  minuit.mnexcm("SET ERRORDEF", argList, 1, errFlag);
622 
623  /* Minimisation strategy: Try MIGRAD minimisation first - which provides also uncertainty estimates.
624  If MIGRAD fails, the more robust SIMPLEX algorithm is used to find the minimum, which does NOT
625  provide uncertainty estimates. In that case, we run MINOS to the find the uncertainties.
626  If SIMPLEX fails too, mark the reconstruction as bad.
627  */
628  if (fixedCore) {
629  minuit.FixParameter(1);
630  minuit.FixParameter(2);
631  }
632  argList[0] = 500; argList[1] = 1;
633  minuit.mnexcm("MIGRAD", argList, 2, errFlag);
634  if (errFlag) {
635  ostringstream msg;
636  msg << "minuit MIGRAD error: " << errFlag;
637  ERROR(msg);
638  minuit.mnexcm("SIMPLEX", argList , 2, errFlag);
639  if (errFlag) {
640  ostringstream msg;
641  msg << "minuit SIMPLEX error: " << errFlag;
642  ERROR(msg);
643  badFit = true;
644  } else {
645  minuit.mnexcm("MINOS", argList , 1, errFlag);
646  if (errFlag) {
647  ostringstream msg;
648  msg << "minuit MINOS error: " << errFlag;
649  ERROR(msg);
650  badFit = true;
651  }
652  }
653  }
654 
655  // Get results
656  double xShift = 0;
657  double xShiftErr = 0;
658  double yShift = 0;
659  double yShiftErr = 0;
660  minuit.GetParameter(0, n19, n19Err);
661  minuit.GetParameter(1, xShift, xShiftErr);
662  minuit.GetParameter(2, yShift, yShiftErr);
663 
664  if (n19 <= 0 || n19Err <= 0 || TMath::IsNaN(n19) || TMath::IsNaN(n19Err)) {
665  ERROR("Fit failed: N19 or N19Err are bogus.");
666  badFit = true;
667  }
668 
669  if (!fFixedCore) {
670  core = utl::Point(xShift, yShift, 0, localCS);
671  coreErr = utl::Vector(xShiftErr, yShiftErr, 0, localCS);
672  }
673 
674  logLikelihoodMin = -minuit.fAmin; // minus sign here, because we minimise -LL in Minuit
675 
676  return !badFit;
677 }
678 
679 
680 void
681 SdSimMuonNumberFitter::DrawLogLikelihood(TVirtualPad* const pad, const double n19, const char* const comment)
682  const
683 {
684  int nPar = 3;
685  double par[3];
686  double value = 0;
687  par[0] = n19;
688  int flag = 0;
689  double* grad = nullptr;
690 
691  INFO("Draw 1");
692  TH2D* const h1 = new TH2D(TString("lh_map1") += comment, "", 100, -25e3, 25e3, 100, -25e3, 25e3);
693  for (int ix = 1; ix < h1->GetNbinsX()+1; ++ix)
694  for(int iy = 1; iy < h1->GetNbinsY()+1; ++iy) {
695  par[1] = h1->GetXaxis()->GetBinCenter(ix);
696  par[2] = h1->GetYaxis()->GetBinCenter(iy);
697  gLikelihood.MinuitFnc(nPar, grad, value, par, flag);
698  h1->SetBinContent(ix,iy,value);
699  }
700 
701  INFO("Draw 2");
702  TH2D* const h2 = new TH2D(TString("lh_map2") += comment, "", 100, -5e3, 5e3, 100, -5e3, 5e3);
703  for (int ix = 1; ix < h2->GetNbinsX()+1; ++ix)
704  for(int iy = 1; iy < h2->GetNbinsY()+1; ++iy) {
705  par[1] = h2->GetXaxis()->GetBinCenter(ix);
706  par[2] = h2->GetYaxis()->GetBinCenter(iy);
707  gLikelihood.MinuitFnc(nPar, grad, value, par, flag);
708  h2->SetBinContent(ix,iy,value);
709  }
710  pad->Divide(2);
711  pad->cd(1);
712  h1->Draw("colz");
713  pad->cd(2);
714  h2->Draw("colz");
715 }
716 
717 
718 void
719 SdSimMuonNumberFitter::DrawMuonDensity(TVirtualPad* const pad, const double n19, const double theta, const double phi, const char* const comment)
720  const
721 {
722  INFO("Draw 1");
723  TH2D* const h1 = new TH2D(TString("nmu_map1") += comment, "", 50, -25e3, 25e3, 50, -25e3, 25e3);
724  for (int ix = 1; ix < h1->GetNbinsX()+1; ++ix)
725  for(int iy = 1; iy < h1->GetNbinsY()+1; ++iy) {
726  const double x = h1->GetXaxis()->GetBinCenter(ix);
727  const double y = h1->GetYaxis()->GetBinCenter(iy);
728  double muons = 0.0;
729  try {
730  muons = n19
731  *fgMuonProfile->NMuon(x,y, theta, phi, 10*EeV);
732  } catch (OutOfBoundException& e)
733  { }
734  h1->SetBinContent(ix, iy, muons);
735  }
736 
737  INFO("Draw 2");
738  TH2D* const h2 = new TH2D(TString("nmu_map2") += comment, "", 50, -5e3, 5e3, 50, -5e3, 5e3);
739  for (int ix = 1; ix < h2->GetNbinsX()+1; ++ix)
740  for(int iy = 1; iy < h2->GetNbinsY()+1; ++iy) {
741  const double x = h2->GetXaxis()->GetBinCenter(ix);
742  const double y = h2->GetYaxis()->GetBinCenter(iy);
743  double muons = 0.0;
744  try {
745  muons = n19
746  * fgMuonProfile->NMuon(x,y, theta, phi, 10*EeV);
747  } catch (OutOfBoundException& e)
748  { }
749  h2->SetBinContent(ix, iy, muons);
750  }
751  pad->Divide(2);
752  pad->cd(1);
753  h1->Draw("colz");
754  pad->cd(2);
755  h2->Draw("colz");
756 }
Class to access station level reconstructed data.
boost::tuple< double, double > Tuple2D
utl::CoordinateSystemPtr GetLocalCoordinateSystem() const
Get the Auger coordinate system associated to the shower core position.
void SetCurvature(const double curvature, const double error)
gaussian curvature = 1 / Rc
Station Level Simulated Data
StationIterator StationsEnd()
End of all stations.
Definition: SEvent.h:59
double RPerp(const Vector &axis, const Vector &station)
void SetTotalSignal(const double signal, const double sErr=0)
Total integrated signal in VEM unit, averaged over pmts.
const double degree
Point object.
Definition: Point.h:32
void SetBarycenter(const utl::Point &bary)
const utl::TimeStamp & GetTimeStamp() const
Get the TimeStamp of the absolute shower core-time.
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
Definition: BasicVector.h:254
void AddStation(const int id, const utl::Point &sPos, const utl::Point &showerOrigin, const utl::CoordinateSystemPtr &coreCS, const unsigned int nmuon)
double Energy(const double beta)
Calculate the electron energy for a relativistic beta.
Detector description interface for Station-related data.
Interface class to access to the SD Reconstruction of a Shower.
int GetNumberOfStations() const
Get total number of stations in the event.
Definition: SEvent.h:124
bool HasRecShower() const
Interface class to access to the SD part of an event.
Definition: SEvent.h:39
void SetAzimuthShowerPlane(const double azimuth)
Azimuth in shower plane coordinates.
ShowerRecData & GetRecShower()
double GetCosTheta(const CoordinateSystemPtr &coordinateSystem) const
cos of zenith (theta) angle
Definition: BasicVector.h:251
bool HasSimShower() const
const double meter
Definition: GalacticUnits.h:29
sevt::StationRecData & GetRecData()
Get station level reconstructed data.
void DrawLogLikelihood(TVirtualPad *const pad, const double n19, const char *const comment) const
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
int GetId() const
Definition: SEvent/Header.h:20
string ToString(const G &g, const CoordinateSystemPtr cs)
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
utl::CoordinateSystemPtr GetSiteCoordinateSystem() const
Get the coordinate system for the site.
Definition: Detector.h:137
CoordinateSystemPtr GetShowerCoordinateSystem(const double theta, const double phi, const Point &core)
double pow(const double x, const unsigned int i)
const double EeV
Definition: GalacticUnits.h:34
bool EnergyFit(const utl::CoordinateSystemPtr &localCS, utl::Point &core, utl::Vector &coreError, double &n19, double &n19Error, double &logLikelihoodMin, const bool fixedCore) const
void SetLDFChi2(const double chi2, const double ndof)
Tuple2D ProjectIntoCorePlane2(const Point &pos, const Point &showerOrigin, const CoordinateSystemPtr &coreCS)
A TimeStamp holds GPS second and nanosecond for some event.
Definition: TimeStamp.h:110
Exception for reporting variable out of valid range.
utl::Point GetPosition() const
Tank position.
constexpr double deg
Definition: AugerUnits.h:140
Interface class to access Shower Simulated parameters.
Definition: ShowerSimData.h:49
void SetCoreError(const utl::Vector &coreerr)
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
utl::Point FindMuonDensityBaryCenter(const std::vector< StationData > &stationList) const
Class representing a document branch.
Definition: Branch.h:107
class to hold data at Station level
void SetLDFResidual(const double LDFresidual)
Residual of lateral fit.
utl::TimeStamp GetSignalStartTime() const
Start time of the signal.
const utl::Vector & GetDirection() const
Get the direction of the shower axis. This is the true direction of shower movement.
void SetT50(const double t50, const double rms)
double GetX(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:206
void DrawMuonDensity(TVirtualPad *const pad, const double n19, const double theta, const double phi, const char *const comment) const
double abs(const SVector< n, T > &v)
void SetAxis(const utl::Vector &axis)
double GetTotalSignal() const
Total integrated signal in VEM unit, averaged over pmts.
const utl::Point & GetPosition() const
Get the position of the shower core.
ParticleVector::const_iterator ConstParticleIterator
Top of the hierarchy of the detector description interface.
Definition: Detector.h:81
fwk::VModule::ResultFlag Finish()
Finish: invoked at end of the run (NOT end of the event)
static int kHASRecoStatus
fwk::VModule::ResultFlag Init()
Initialize: invoked at beginning of run (NOT beginning of event)
constexpr double g
Definition: AugerUnits.h:200
double GetEnergy() const
Get the energy of the shower primary particle.
Definition: ShowerSimData.h:89
void GetData(bool &b) const
Overloads of the GetData member template function.
Definition: Branch.cc:644
std::string GetName() const
function to get the Branch name
Definition: Branch.cc:374
void SetCoreTime(const utl::TimeStamp &coreTime, const utl::TimeInterval &coreTimeErr)
Station & GetStation(const int stationId)
retrieve station by id throw utl::NonExistentComponentException if n.a.
Definition: SEvent.h:116
static void N19FitFnc(int &nPar, double *const grad, double &value, double *const par, const int flag)
ParticleIterator ParticlesBegin()
Beginning of simulated particles entering the station.
void SetSignalStartTime(const utl::TimeStamp time)
Start time of the signal.
void MakeRecData()
Make station reconstructed data object.
fwk::VModule::ResultFlag Run(evt::Event &event)
Run: invoked once per event.
double GetY(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:209
constexpr double kSpeedOfLight
A TimeInterval is used to represent time elapsed between two events.
Definition: TimeInterval.h:43
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
static Likelihood gLikelihood
bool HasRecData() const
Check whether station reconstructed data exists.
StationIterator StationsBegin()
Beginning of all stations.
Definition: SEvent.h:57
Vector object.
Definition: Vector.h:30
Detector description interface for SDetector-related data.
Definition: SDetector.h:42
MuonProfile * fgMuonProfile
void SetCorePosition(const utl::Point &core)
sevt::Header & GetHeader()
Definition: SEvent.h:155
Main configuration utility.
Definition: CentralConfig.h:51
void SetLDFLikelihood(const double likelihood)
void SetEnergy(const double energy, const double error)
void SetLDFRecStage(const double stage)
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:212
const Station & GetStation(const int stationId) const
Get station by Station Id.
Definition: SDetector.cc:192
double LocalCosTheta(const Point &pos, const Point &showerOrigin)
const int nPar
Definition: GeomAsym.h:37
void MinuitFnc(int &nPar, double *const grad, double &value, double *const par, const int flag)
boost::indirect_iterator< InternalConstStationIterator, const Station & > ConstStationIterator
Definition: SEvent.h:54
void SetSPDistance(const double distance, const double error)
Distance from core in shower plane coordinates.
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
ParticleIterator ParticlesEnd()
End of simulated particles entering the station.
bool HasSRecShower() const
bool HasSEvent() const
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)
Tuple2D ProjectIntoCorePlane(const Point &pos, const Point &showerOrigin, const CoordinateSystemPtr &coreCS)
double RPerp2(const Vector &axis, const Vector &station)

, generated on Tue Sep 26 2023.