31 #include <fwk/CentralConfig.h>
32 #include <fwk/RandomEngineRegistry.h>
34 #include <evt/Event.h>
35 #include <evt/ShowerSimData.h>
37 #include <sevt/SEvent.h>
38 #include <sevt/Station.h>
39 #include <sevt/StationRecData.h>
40 #include <sevt/StationTriggerData.h>
41 #include <sevt/EventTrigger.h>
43 #include <utl/AxialVector.h>
44 #include <utl/ErrorLogger.h>
45 #include <utl/MathConstants.h>
46 #include <utl/Particle.h>
47 #include <utl/PhysicalConstants.h>
48 #include <utl/PhysicalFunctions.h>
49 #include <utl/Reader.h>
50 #include <utl/RandomEngine.h>
51 #include <utl/UTMPoint.h>
53 #include <det/Detector.h>
54 #include <sdet/SDetector.h>
56 #include <atm/Atmosphere.h>
57 #include <atm/ProfileResult.h>
59 #include <CLHEP/Random/RandPoisson.h>
60 #include <CLHEP/Random/Randomize.h>
61 #include <CLHEP/Random/RandGauss.h>
76 using CLHEP::RandFlat;
77 using CLHEP::RandPoisson;
82 using namespace LDFTestKG;
89 const double LDFTest::fNerlingA1a = 6.42522;
90 const double LDFTest::fNerlingA1b = -1.53183;
91 const double LDFTest::fNerlingA2a = 168.168;
92 const double LDFTest::fNerlingA2b = -42.1368;
103 fRandomEngine = &RandomEngineRegistry::GetInstance().Get(RandomEngineRegistry::ePhysics);
107 LDFTest::~LDFTest() {
117 ERROR (
"Could not find branch SdSimpleSim");
123 if (n_sampleB == 0) {
124 ERROR (
"Could not find branch n_sample");
135 if (MuonRScaleB == 0) {
136 ERROR (
"Could not find branch MuonRScale");
139 MuonRScaleB.
GetData (fMuonRScale);
146 ERROR (
"Could not find branch em_age");
149 em_ageB.
GetData (fEMAgeFactor);
165 INFO(
" LDFTest -> Run ");
169 return eContinueLoop;
174 return eContinueLoop;
177 return eContinueLoop;
180 return eContinueLoop;
183 return eContinueLoop;
185 bool HasMuonProfile =
188 bool HasGammaProfile =
191 bool HasElectronProfile =
195 if (!HasMuonProfile ||
197 !HasElectronProfile) {
198 ERROR (
"Input file not suitable for LDFTest");
199 return eContinueLoop;
239 double Zenith = SimShower.GetZenith();
240 double cosTheta = cos (Zenith);
255 double ProfileMaxDepth = SimProfile [SimProfile. GetNPoints() - 1]. X();
263 double XobsVert = depthProfile.
Y (HeightObs);
264 double Temperature = temperatureProfile.
Y (HeightObs);
265 static double g_earth = 9.81 *
m/(
s*
s);
266 double Pressure = XobsVert * g_earth;
270 cout <<
" start " << endl;
274 double rmax = 4100*
m;
276 double dr = (rmax-rmin) / (nBins);
279 TGraph ldfEl (nBins);
280 TGraph ldfGa (nBins);
281 TGraph ldfMu (nBins);
282 TGraph ldfSum (nBins);
284 TGraph rhoEl (nBins);
285 TGraph rhoGa (nBins);
286 TGraph rhoMu (nBins);
287 TGraph rhoSum (nBins);
291 for (
double r=rmin; r<rmax; r+=dr) {
296 double Xobs = XobsVert / cosTheta;
300 bool ShowerProfileRangeExceeded =
false;
301 if (Xobs>ProfileMaxDepth) {
303 ShowerProfileRangeExceeded =
true;
304 Xobs = ProfileMaxDepth;
313 Nch = SimProfile.
Y (Xobs);
314 if (HasMuonProfile) {
315 Nmu = SimMuonProfile.
Y (Xobs);
320 if (HasGammaProfile) {
321 Ng = SimGammaProfile.
Y (Xobs);
326 if (HasElectronProfile) {
327 Ne = SimElectronProfile.
Y (Xobs);
339 double S = CalculateTankSignal (r, 1.8*
m, 1.2*
m, Zenith,
344 if (fSmu) ldfMu.SetPoint (iPoint, (r), (fSmu));
345 if (fSel) ldfEl.SetPoint (iPoint, (r), (fSel));
346 if (fSga) ldfGa.SetPoint (iPoint, (r), (fSga));
347 if (fSsum) ldfSum.SetPoint (iPoint, (r), (fSsum));
349 rhoMu.SetPoint (iPoint, (r), (fRhomu));
350 rhoEl.SetPoint (iPoint, (r), (fRhoel));
351 rhoGa.SetPoint (iPoint, (r), (fRhoga));
352 rhoSum.SetPoint (iPoint, (r), (fRhosum));
358 cout <<
" S/vem " << S <<
" Energy/EeV " << simEnergy/
EeV << endl;
363 ldfSum.SetLineColor (1);
364 ldfSum.SetLineWidth (2);
365 ldfSum.SetMarkerColor (1);
366 ldfMu.SetLineColor (2);
367 ldfMu.SetLineWidth (2);
368 ldfMu.SetMarkerColor (2);
369 ldfEl.SetLineColor (3);
370 ldfEl.SetLineWidth (2);
371 ldfEl.SetMarkerColor (3);
372 ldfGa.SetLineColor (4);
373 ldfGa.SetLineWidth (2);
374 ldfGa.SetMarkerColor (4);
376 rhoSum.SetLineColor (1);
377 rhoSum.SetLineWidth (2);
378 rhoSum.SetMarkerColor (1);
379 rhoMu.SetLineColor (2);
380 rhoMu.SetLineWidth (2);
381 rhoMu.SetMarkerColor (2);
382 rhoEl.SetLineColor (3);
383 rhoEl.SetLineWidth (2);
384 rhoEl.SetMarkerColor (3);
385 rhoGa.SetLineColor (4);
386 rhoGa.SetLineWidth (2);
387 rhoGa.SetMarkerColor (4);
389 TLegend *l =
new TLegend (.5,.6,.95,.9);
392 l->AddEntry (&ldfMu,
"muons");
393 l->AddEntry (&ldfEl,
"electrons");
394 l->AddEntry (&ldfGa,
"gammas");
398 cName <<
"c_" << fEvent;
399 TCanvas
c (cName.str().c_str());
402 TH2F axis1 (
"axis1",
"axis",2,200,4100,2,0.001,200);
403 TH2F axis2 (
"axis2",
"axis",2,200,4100,2,0.001,200);
405 gStyle->SetOptStat (0);
406 gStyle->SetOptTitle (0);
408 axis1.SetXTitle (
"r/m");
409 axis1.SetYTitle (
"S/VEM");
423 axis2.SetXTitle (
"r/m");
424 axis2.SetYTitle (
"1/m^2");
435 TFile f (
"ldf.root",
"update");
436 c.Write (
"",TFile::kOverwrite);
473 double C = TMath::Gamma (4.5-s) /
474 (TMath::Gamma (s) * TMath::Gamma (4.5-2*s));
476 double rho = C * N/(2.*
kPi*Rmoliere*Rmoliere);
478 rho *=
pow (R, s-2.);
479 rho *=
pow (1.+R, s-4.5);
489 double LDFTest::TankIntersection (
double r,
495 double cosTheta = cos (theta);
496 double sinTheta = sin (theta);
498 double UntilBottom = 0;
500 UntilBottom = z / cos (theta);
505 double UntilSide = 0;
507 UntilSide = (TankRadius + r * cos (phi) -
509 sqrt (TankRadius*TankRadius -
510 r * r * sin (phi) * sin (phi) )))
517 return min (UntilSide, UntilBottom);
523 double LDFTest::LTP (
double r,
530 return 1. / (1. + exp ((r-Rltp)/Wltp));
535 double LDFTest::SampleEnergy (
double Emin,
543 double a1 = 6.42522 - 1.53183 * Age;
544 double a2 = 168.168 - 42.1368 * Age;
546 double F2max = NerlingF2 (Emin, a2, Age);
557 r1 = RandFlat::shoot(&fRandomEngine->GetEngine(), 0., 1.);
558 r2 = RandFlat::shoot(&fRandomEngine->GetEngine(), 0., 1.);
560 E = exp (r1 * log (Emax+a1) +
561 (1-r1) * log (Emin+a1)) - a1;
564 accept = NerlingF2 (E, a2, Age);
569 }
while (accept/F2max < r2);
589 double LDFTest::NerlingF1 (
double E,
596 double LDFTest::NerlingF2 (
double E,
600 return 1. /
pow ((E+a2), s);
605 double LDFTest::CalculateTankSignal (
double CoreDistance,
606 double TankRadius,
double TankHeight,
double Zenith,
607 double Age,
double Rm,
608 double Ne,
double Ng,
double Nmu) {
610 double cosTheta = cos (Zenith);
611 double sinTheta = sin (Zenith);
613 double TankProjTop =
kPi * TankRadius * TankRadius * cosTheta;
614 double TankProjSide = TankHeight * 2.* TankRadius * sinTheta;
615 double TankProjArea = TankProjTop + TankProjSide;
619 double RhoElectrons =
NKG (Ne, Rm, CoreDistance, Age/fEMAgeFactor);
620 double RhoGammas =
NKG (Ng, Rm, CoreDistance, Age/fEMAgeFactor);
621 double RhoMuons =
NKG (Nmu, fMuonRScale, CoreDistance, Age);
630 fRhoel = RhoElectrons;
649 double nElectrons = TankProjArea * RhoElectrons;
650 double nGammas = TankProjArea * RhoGammas;
651 double nMuons = TankProjArea * RhoMuons;
653 cout <<
" Zenith " << Zenith/
deg << endl;
654 cout <<
" A " << TankProjArea/
m/
m << endl;
655 cout <<
" rho " << RhoElectrons <<
" " << RhoGammas <<
" " << RhoMuons << endl;
656 cout <<
" nPart " << nElectrons <<
" " << nGammas <<
" " << nMuons << endl;
664 double TankSignal = 0;
673 double Weight = nMuons/nSample;
674 for (
int iSample=0; iSample<nSample; iSample++) {
676 double p = RandFlat::shoot(&fRandomEngine->GetEngine(), 0, 1);
679 if (p<TankProjTop/TankProjArea) {
682 r =
sqrt (RandFlat::shoot(&fRandomEngine->GetEngine(),
685 phi = RandFlat::shoot(&fRandomEngine->GetEngine(),
696 phi = RandFlat::shoot (&fRandomEngine->GetEngine(),
699 z = RandFlat::shoot (&fRandomEngine->GetEngine(),
704 double TrackLength = TankIntersection (r,
723 double nEM = nElectrons;
726 double Weight = nEM/nSample;
727 for (
int iSample=0; iSample<nSample; iSample++) {
730 static double Emin = 1.e-2*
MeV;
731 static double Emax = 1.e+5*
MeV;
732 double Eem = SampleEnergy (Emin, Emax, Age);
743 double Weight = nEM/nSample;
744 for (
int iSample=0; iSample<nSample; iSample++) {
747 static double Emin = 1.e-2*
MeV;
748 static double Emax = 1.e+5*
MeV;
749 double Eem = SampleEnergy (Emin, Emax, Age);
760 fSsum /= TankProjArea;
761 fSga /= TankProjArea;
762 fSel /= TankProjArea;
763 fSmu /= TankProjArea;
780 {1.9, 2.2, 3.6, 5.1},
781 {1.9, 3.0, 3.5, 4.8},
782 {2.5, 3.3, 4.1, 5.1},
783 {3.5, 3.8, 4.2, 5.4},
784 {4.2, 4.8, 4.8, 5.0}};
795 double LDFTest::T1TriggerProbability (
double signal,
double S1000,
double theta) {
797 cout <<
" tgheta " << theta << endl;
799 static double n = 2.8;
818 cout <<
" pT1: " << theta <<
" " << S1000 <<
" " << signal << endl;
822 for (thetaBin=0; thetaBin<4; thetaBin++) {
829 for (s1000Bin=0; s1000Bin<3; s1000Bin++) {
843 double s1000_1 = theta_s1000_11 + (theta_s1000_12-theta_s1000_11) * delta_s1000;
844 double s1000_2 = theta_s1000_21 + (theta_s1000_22-theta_s1000_21) * delta_s1000;
847 double S_half = s1000_1 + (s1000_2-s1000_1) * delta_theta;
850 cout <<
" S_0.5 " << S_half << endl;
853 double p =
pow (signal,n);
854 p /= (p +
pow (S_half,n));
bool HasDirection() const
Check initialization of shower geometry.
const utl::TimeStamp & GetTimeStamp() const
Get the TimeStamp of the absolute shower core-time.
const evt::VGaisserHillasParameter & GetGHParameters() const
Get the Gaisser-Hillas parameters of the shower.
static double fgTriggerPropShalf[5][4]
Class to hold collection (x,y) points and provide interpolation between them.
bool HasSimShower() const
static double kTrackPerGEV
#define INFO(message)
Macro for logging informational messages.
void Init()
Initialise the registry.
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
double pow(const double x, const unsigned int i)
static double fgTriggerS1000Bins[4]
double Y(const double x) const
Get the Y value (coordinate) for given X (ordinate)
A TimeStamp holds GPS second and nanosecond for some event.
bool HasPosition() const
Check initialization of shower geometry.
Interface class to access Shower Simulated parameters.
const atm::Atmosphere & GetAtmosphere() const
Class representing a document branch.
Reference ellipsoids for UTM transformations.
double MoliereRadius(double temperature, double pressure, const double cosTheta)
The Moliere Radius (2 radiation length above obs-level, GAP-1998-002)
Class describing the Atmospheric profile.
const utl::Point & GetPosition() const
Get the position of the shower core.
Top of the hierarchy of the detector description interface.
Triple PointToLatitudeLongitudeHeight(const Point &thePoint) const
Convert Point to Lat/Long/Height.
const atm::ProfileResult & EvaluateDepthVsHeight() const
Tabulated function giving Y=depth as a function of X=height.
double GetEnergy() const
Get the energy of the shower primary particle.
void GetData(bool &b) const
Overloads of the GetData member template function.
static double kMeterPerVEM
ResultFlag
Flag returned by module methods to the RunController.
double ShowerAge(const double slantDepth, const double showerMax)
General definition of shower age.
bool HasGHParameters() const
Check initialization of the Gaisser-Hillas parameters.
Main configuration utility.
const atm::ProfileResult & EvaluateHeightVsDepth() const
Tabulated function giving Y=height as a function of X=depth.
static double fgTriggerThetaBins[5]
double Y(const double x) const
Get or interpolate the Y value that corresponds to parameter x.
#define ERROR(message)
Macro for logging error messages.
double NKG(const double r, const double n, const double rG, const double s)
bool HasLongitudinalProfile(const ProfileType type=eCharged) const
Check initialization of the longitudinal profile.
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)
const atm::ProfileResult & EvaluateTemperatureVsHeight() const
Tabulated function giving Y=temperature as a function of X=height.
const utl::TabulatedFunction & GetLongitudinalProfile(const ProfileType type=eCharged) const
Get the longitudinal charge profile of the shower.