3 #include <fwk/LocalCoordinateSystem.h>
4 #include <fwk/CentralConfig.h>
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>
16 #include <sdet/MuonProfile.h>
17 #include <utl/HASUtilities.h>
19 #include <det/Detector.h>
21 #include <sdet/SDetector.h>
23 #include <evt/Event.h>
24 #include <evt/ShowerSimData.h>
25 #include <evt/ShowerRecData.h>
26 #include <evt/ShowerSRecData.h>
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>
44 #include <TVirtualPad.h>
46 #include <boost/tuple/tuple.hpp>
48 using namespace SdSimMuonNumberFitterNS;
51 using namespace HASUtilities;
58 typedef boost::tuple<double, double>
Tuple2D;
71 const double scal = axis*station;
72 return station*station - scal*scal;
92 << g.GetX(cs)/
meter <<
", "
93 << g.GetY(cs)/
meter <<
", "
94 << g.GetZ(cs)/
meter <<
") [m]";
104 return CoordinateSystem::RotationY(theta,
105 CoordinateSystem::RotationZ(phi,
106 LocalCoordinateSystem::Create(core)));
115 const double dz = pos.
GetZ(coreCS);
116 const Vector stationToOrigin = showerOrigin-pos;
117 const Point corePlanePos = stationToOrigin/stationToOrigin.
GetZ(coreCS)*dz + pos;
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;
138 const Vector stationToOrigin = showerOrigin - pos;
139 return stationToOrigin.
GetCosTheta(LocalCoordinateSystem::Create(pos));
149 const double sTheta = acos(
LocalCosTheta(pos, showerOrigin));
150 fStationList.push_back(
InternalStationData(
id, sPosProjXY.get<0>(), sPosProjXY.get<1>(), sTheta,nmuon));
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;
172 const int& nmu = sIt->fNMuon;
173 double nmuExpected = 0;
181 double p = TMath::Poisson(nmu, nmuExpected);
183 logLikelihood += log(p);
185 logLikelihood += -DBL_MAX_EXP;
188 if (logLikelihood < -DBL_MAX) {
189 ERROR(
"logLikelihood = -infinity!");
194 if (logLikelihood != logLikelihood) {
195 ERROR(
"Likelihood = nan!");
200 value = -logLikelihood;
238 fFixedCore = bool(topB.
GetChild(
"FixedCore"));
240 if (fVerbosity >= ErrorLogger::eInfo) {
242 msg <<
"\nParameters:\n"
243 <<
" Verbosity : " << fVerbosity <<
"\n"
244 <<
" MaxDistanceZeroSignalStations : " << fSilentRadius <<
" m\n"
245 <<
" MuonProfile : " << muonProfileBranch.
GetName()
248 <<
" EnergyConstant(EnergyConversion): " << fEnergyConstant <<
" eV\n"
249 <<
" Gamma (EnergyConversion): " << fGamma <<
"\n"
250 <<
" Fixed core : " << (fFixedCore ?
"yes\n" :
"no\n");
263 return eContinueLoop;
265 return eContinueLoop;
269 const sdet::SDetector& sDetector = det::Detector::GetInstance().GetSDetector();
274 ShowerSRecData& showersrec =
event.GetRecShower().GetSRecShower();
282 const double energyMC = showerSimData.
GetEnergy();
283 const double thetaMC = showerSimData.GetZenith();
284 const double phiMC = showerSimData.GetAzimuth();
287 vector<StationData> candidateList;
288 vector<StationData> silentList;
295 sd.
fId = sIt->GetId();
300 bool noParticleData =
true;
303 noParticleData =
false;
306 const TimeStamp pTime = simTime + it->GetTime();
309 if (pTime < sd.
fTime)
312 if (noParticleData && sIt->IsCandidate() && sIt->HasRecData()) {
320 candidateList.push_back(sd);
321 else if (
RPerp(showerAxis, sd.
fPos - simCore) < fSilentRadius)
322 silentList.push_back(sd);
325 if (fVerbosity > ErrorLogger::eDebug) {
326 for (
unsigned int i = 0; i < candidateList.size(); ++i) {
328 cerr <<
"Station " << sd.
fId <<
": " << sd.
fNMuon << endl;
332 if(fVerbosity > ErrorLogger::eInfo) {
335 <<
"\tThetaMC " << showerSimData.GetZenith()/
deg <<
" [deg]" <<
"\n"
337 <<
"\t# number of candidate stations = " << candidateList.size() <<
"\n"
338 <<
"\t# number of silent stations = " << silentList.size() << endl;
343 if (candidateList.size() < 3) {
344 INFO(
"Not enough stations.");
345 showersrec.SetS1000(0, 0);
349 const Point barycenter = FindMuonDensityBaryCenter(candidateList);
353 Point showerOrigin = barycenter + showerAxis*AverageCurvatureRadius(thetaMC);
357 for (vector<StationData>::const_iterator sIt = candidateList.begin();
358 sIt != candidateList.end(); ++sIt) {
364 const double signal = sIt->fNMuon;
366 const TimeStamp sTime = sIt->fTime + (coreTime - simTime);
374 const bool notInMuonProfileRange =
377 if (notInMuonProfileRange) {
378 if (fVerbosity > ErrorLogger::eInfo) {
380 msg <<
"Theta = " << thetaMC/
degree <<
" Deg was not in valid range of\n ";
381 if (notInMuonProfileRange)
382 msg <<
" MuonProfile";
393 double logLikelihoodMin = 0;
395 for (vector<StationData>::const_iterator sIt=candidateList.begin();
396 sIt != candidateList.end(); ++sIt) {
399 for (vector<StationData>::const_iterator sIt = silentList.begin();
400 sIt != silentList.end(); ++sIt) {
407 bool success = EnergyFit(baryCS, core, coreErr, n19, n19Err, logLikelihoodMin,
true);
409 ERROR(
"Failed N19 estimate fit (fixed core to barycenter)");
410 showersrec.SetS1000(0, 0);
413 const double n19estimate = n19;
415 if (200 <= fVerbosity) {
417 int phii = int(phiMC/
degree);
421 TFile f(buf,
"RECREATE");
422 TCanvas*
const c =
new TCanvas;
425 DrawMuonDensity(gPad, n19estimate, thetaMC, phiMC,
"est");
427 DrawLogLikelihood(gPad, n19estimate,
"est");
433 success = EnergyFit(baryCS, core, coreErr, n19, n19Err, logLikelihoodMin,
false);
435 showersrec.SetS1000(n19estimate, 0);
436 ERROR(
"Failed N19 + core fit");
438 if (100 <= fVerbosity && fVerbosity < 200) {
440 int phii = int(phiMC/
degree);
444 TFile f(buf,
"RECREATE");
445 TCanvas*
const c =
new TCanvas;
448 DrawMuonDensity(gPad, n19estimate, thetaMC, phiMC,
"est");
450 DrawLogLikelihood(gPad, n19estimate,
"est");
458 showerOrigin = core + showerAxis*AverageCurvatureRadius(thetaMC);
461 const double Energy = fEnergyConstant *
pow(n19,fGamma);
462 const double EnergyError = n19Err * fEnergyConstant*fGamma*
pow(n19, fGamma-1);
464 const double diffToMC = Energy/energyMC - 1;
465 const double diffToMCSigma = (Energy - energyMC) / EnergyError;
467 if (fVerbosity > ErrorLogger::eInfo) {
470 <<
"\tEnergy - XML Calibration : " << Energy/
EeV <<
" +/- " << EnergyError/
EeV
472 <<
"\tMonte-Carlo Energy : " << energyMC/
EeV <<
" [EeV]"
473 <<
" ( " << setprecision(3) << diffToMC*100.
474 <<
" % | " << setprecision(3) << diffToMCSigma <<
" std.dev. )" << endl;
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;
499 sPosProjXY.get<1>(), thetaMC, phiMC, 10*
EeV);
504 const double signalPred = muons;
508 const double signal = sIt->fNMuon;
509 const double sigma =
sqrt(signalPred);
510 const double res = (signal - signalPred) / sigma;
512 const double rho =
RPerp(showerAxis, sPos - core);
513 const double drho = 0;
515 chi2 += (res*res) / signalPred;
528 showersrec.
SetAxis(showerAxis);
530 showersrec.
SetEnergy(Energy, EnergyError);
531 showersrec.SetS1000(n19, n19Err);
552 const det::Detector& detector = det::Detector::GetInstance();
558 const Point siteOrigin(0,0,0, siteCS);
561 Vector barySum(0,0,0, siteCS);
562 double weightSum = 0;
564 for (vector<StationData>::const_iterator it = stationList.begin();
565 it != stationList.end(); ++it) {
567 const double weight =
sqrt(
double(sd.
fNMuon));
569 barySum += weight * (sd.
fPos - siteOrigin);
574 ERROR(
"sum of weights = 0");
578 barySum /= weightSum;
579 Point barycenter = siteOrigin + barySum;
582 msg <<
"\nbarycenter = " <<
ToString(barycenter, fSimCoreCS) <<
" (showerGroundCS)" <<
"\n";
598 Point& core,
Vector& coreErr,
double& n19,
double& n19Err,
599 double& logLikelihoodMin,
const bool fixedCore)
610 minuit.mnexcm(
"SET PRINTOUT", argList, 1, errFlag);
611 minuit.mnexcm(
"SET NOWARNINGS", argList, 0, errFlag);
612 minuit.SetPrintLevel(-1);
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);
621 minuit.mnexcm(
"SET ERRORDEF", argList, 1, errFlag);
629 minuit.FixParameter(1);
630 minuit.FixParameter(2);
632 argList[0] = 500; argList[1] = 1;
633 minuit.mnexcm(
"MIGRAD", argList, 2, errFlag);
636 msg <<
"minuit MIGRAD error: " << errFlag;
638 minuit.mnexcm(
"SIMPLEX", argList , 2, errFlag);
641 msg <<
"minuit SIMPLEX error: " << errFlag;
645 minuit.mnexcm(
"MINOS", argList , 1, errFlag);
648 msg <<
"minuit MINOS error: " << errFlag;
657 double xShiftErr = 0;
659 double yShiftErr = 0;
660 minuit.GetParameter(0, n19, n19Err);
661 minuit.GetParameter(1, xShift, xShiftErr);
662 minuit.GetParameter(2, yShift, yShiftErr);
664 if (n19 <= 0 || n19Err <= 0 || TMath::IsNaN(n19) || TMath::IsNaN(n19Err)) {
665 ERROR(
"Fit failed: N19 or N19Err are bogus.");
670 core =
utl::Point(xShift, yShift, 0, localCS);
671 coreErr =
utl::Vector(xShiftErr, yShiftErr, 0, localCS);
674 logLikelihoodMin = -minuit.fAmin;
689 double* grad =
nullptr;
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);
698 h1->SetBinContent(ix,iy,value);
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);
708 h2->SetBinContent(ix,iy,value);
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);
734 h1->SetBinContent(ix, iy, muons);
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);
749 h2->SetBinContent(ix, iy, muons);
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.
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.
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
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.
bool HasRecShower() const
Interface class to access to the SD part of an event.
void SetAzimuthShowerPlane(const double azimuth)
Azimuth in shower plane coordinates.
ShowerRecData & GetRecShower()
double GetCosTheta(const CoordinateSystemPtr &coordinateSystem) const
cos of zenith (theta) angle
bool HasSimShower() const
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.
string ToString(const G &g, const CoordinateSystemPtr cs)
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
utl::CoordinateSystemPtr GetSiteCoordinateSystem() const
Get the coordinate system for the site.
CoordinateSystemPtr GetShowerCoordinateSystem(const double theta, const double phi, const Point &core)
double pow(const double x, const unsigned int i)
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.
Exception for reporting variable out of valid range.
utl::Point GetPosition() const
Tank position.
Interface class to access Shower Simulated parameters.
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.
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
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.
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)
double GetEnergy() const
Get the energy of the shower primary particle.
void GetData(bool &b) const
Overloads of the GetData member template function.
std::string GetName() const
function to get the Branch name
virtual ~SdSimMuonNumberFitter()
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.
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
constexpr double kSpeedOfLight
A TimeInterval is used to represent time elapsed between two events.
ResultFlag
Flag returned by module methods to the RunController.
static Likelihood gLikelihood
bool HasRecData() const
Check whether station reconstructed data exists.
StationIterator StationsBegin()
Beginning of all stations.
Detector description interface for SDetector-related data.
MuonProfile * fgMuonProfile
void SetCorePosition(const utl::Point &core)
sevt::Header & GetHeader()
Main configuration utility.
void SetLDFLikelihood(const double likelihood)
void SetPhi(const double phi)
void SetEnergy(const double energy, const double error)
void SetTheta(const double theta)
void SetLDFRecStage(const double stage)
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
const Station & GetStation(const int stationId) const
Get station by Station Id.
double LocalCosTheta(const Point &pos, const Point &showerOrigin)
void MinuitFnc(int &nPar, double *const grad, double &value, double *const par, const int flag)
boost::indirect_iterator< InternalConstStationIterator, const Station & > ConstStationIterator
void SetSPDistance(const double distance, const double error)
Distance from core in shower plane coordinates.
#define ERROR(message)
Macro for logging error messages.
ParticleIterator ParticlesEnd()
End of simulated particles entering the station.
bool HasSRecShower() 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)