18 #include <fwk/CentralConfig.h>
19 #include <fwk/CoordinateSystemRegistry.h>
20 #include <fwk/RandomEngineRegistry.h>
22 #include <evt/Event.h>
23 #include <evt/ShowerSimData.h>
25 #include <sevt/SEvent.h>
26 #include <sevt/Header.h>
27 #include <sevt/Station.h>
28 #include <sevt/StationRecData.h>
29 #include <sevt/StationSimData.h>
30 #include <sevt/StationTriggerData.h>
31 #include <sevt/EventTrigger.h>
33 #include <utl/AxialVector.h>
34 #include <utl/ErrorLogger.h>
35 #include <utl/MathConstants.h>
36 #include <utl/Particle.h>
37 #include <utl/PhysicalConstants.h>
38 #include <utl/PhysicalFunctions.h>
39 #include <utl/Reader.h>
40 #include <utl/RandomEngine.h>
41 #include <utl/UTMPoint.h>
43 #include <det/Detector.h>
44 #include <sdet/SDetector.h>
46 #include <atm/Atmosphere.h>
47 #include <atm/ProfileResult.h>
48 #include <atm/InclinedAtmosphericProfile.h>
53 #include <CLHEP/Random/RandPoisson.h>
54 #include <CLHEP/Random/Randomize.h>
55 #include <CLHEP/Random/RandGauss.h>
56 #include <CLHEP/Random/RandFlat.h>
64 #include <boost/range/iterator_range.hpp>
68 using CLHEP::RandGauss;
69 using CLHEP::RandFlat;
70 using CLHEP::RandPoisson;
77 using namespace SdSimpleSimKG;
80 const double SdSimpleSim::fNerlingA1a = 6.42522;
81 const double SdSimpleSim::fNerlingA1b = -1.53183;
82 const double SdSimpleSim::fNerlingA2a = 168.168;
83 const double SdSimpleSim::fNerlingA2b = -42.1368;
92 SdSimpleSim::SdSimpleSim() :
97 fNoiseRatePerStation(1.0065346445791242e+02 *
hertz)
107 ERROR(
"Could not find branch SdSimpleSim");
116 INFO(
"Using T2 life manager for SD station status.");
133 INFO(
"Write time model statistics to root file.");
138 TFile*
const StatFile = TFile::Open(FileName.c_str(),
"recreate");
156 fStatTree =
new TTree(
"stat",
"time model statistics");
185 " generate noise: " <<
fNoise <<
"\n"
188 " max no. samplings: " <<
fNSample <<
"\n"
221 const bool hasMuonProfile =
224 const bool hasMuonProductionProfile =
227 const bool hasGammaProfile =
230 const bool hasElectronProfile =
233 const bool hasdEdXProfile =
236 if (!hasMuonProfile || !hasGammaProfile || !hasElectronProfile) {
237 ERROR(
"Input file not suitable for SdSimpleSim");
242 ERROR(
"Cannot use MuonProductionHeight from simulation");
252 if (hasMuonProductionProfile)
258 fProfileExtrapolation[ShowerSimData::eMuonProduction] = fitMuonProd;
261 fProfileExtrapolation[ShowerSimData::eEnergyDeposit] = fitdEdX;
274 sEventHeader.
SetTime(coreTime);
292 dbg <<
" Sim-Parameters: Xmax= "<<Xmax/
g*
cm2;
302 const double Zenith = (-SimShower.
GetDirection()).GetTheta(localCS);
304 const double cosTheta = cos(Zenith);
305 const double absCosTheta = std::fabs(cosTheta);
355 ERROR(
"No muon production profile !!!!!!!!!");
366 double ProfileMaxDepth = SimProfile[SimProfile. GetNPoints() - 1].X();
371 dbg <<
" max prof depth " << ProfileMaxDepth/
g*
cm*
cm
372 <<
" " << SimMuonProfile[0].X()/
g*
cm2
373 <<
" " << SimMuonProfile[SimMuonProfile.
GetNPoints()-1].X()/
g*
cm2;
382 const double atmDistanceMin = slantDepthVsDistance.
MinX();
383 const double atmDistanceMax = slantDepthVsDistance.
MaxX();
384 const double AtmDepthMin = depthProfile.
Y(depthProfile.
MaxX());
385 const double AtmDepthMax = depthProfile.
Y(depthProfile.
MinX());
386 const double XobsVert = depthProfile.
MinX() < HeightObs ?
387 depthProfile.
Y(HeightObs) :
389 const double Temperature =
390 temperatureProfile.
Y(fmax(depthProfile.
MinX(), HeightObs));
391 static double g_earth = 9.81 *
m/(
s*
s);
392 const double Pressure = XobsVert * g_earth;
394 int lorenzoPrimary = -1;
396 switch (simPrimary) {
407 ERROR(
"Unknown lorenzoPrimary!");
436 double Xvert, HeightX, z;
440 xMin = SimProfile[0].X();
441 xMax = SimProfile[nBin-1].X();
442 fCharged =
new TProfile(
"charged",
"charged profile",
443 nBin, xMin/
g*
cm*
cm, xMax/
g*cm*cm);
444 Xvert = xMin * absCosTheta;
445 if (Xvert < AtmDepthMin)
447 if (Xvert > AtmDepthMax)
449 HeightX = heightProfile.
Y(Xvert);
450 zMax = (HeightX - HeightObs) / absCosTheta;
451 Xvert = xMax*absCosTheta;
452 if (Xvert < AtmDepthMin)
454 if (Xvert > AtmDepthMax)
456 HeightX = heightProfile.
Y(Xvert);
457 zMin = (HeightX - HeightObs) / absCosTheta;
458 fCharged_vs_z =
new TProfile(
"charged_vs_z",
"charged profile vs z",
462 iBin != SimProfile.
End(); ++iBin) {
466 Xvert = iBin->X() * absCosTheta;
467 if (Xvert < AtmDepthMin || Xvert > AtmDepthMax)
469 HeightX = heightProfile.
Y(Xvert);
470 z = (HeightX - HeightObs) / absCosTheta;
477 if (hasGammaProfile) {
479 xMin = SimGammaProfile[0].X();
480 xMax = SimGammaProfile[nBin-1].X();
481 fGamma =
new TProfile(
"gamma",
"gamma profile",
482 nBin, xMin/
g*cm*cm, xMax/
g*cm*cm);
483 Xvert = xMin * absCosTheta;
484 if (Xvert < AtmDepthMin)
486 if (Xvert > AtmDepthMax)
488 HeightX = heightProfile.
Y(Xvert);
489 zMax = (HeightX - HeightObs) / absCosTheta;
490 Xvert = xMax * absCosTheta;
491 if (Xvert < AtmDepthMin)
493 if (Xvert > AtmDepthMax)
495 HeightX = heightProfile.
Y(Xvert);
496 zMin = (HeightX - HeightObs) / absCosTheta;
497 fGamma_vs_z =
new TProfile(
"gamma_vs_z",
"gamma profile vs z",
501 x != SimGammaProfile.
End(); ++x) {
505 Xvert = x->X() * absCosTheta;
506 if (Xvert < AtmDepthMin || Xvert > AtmDepthMax)
508 HeightX = heightProfile.
Y(Xvert);
509 z = (HeightX - HeightObs) / absCosTheta;
518 if (hasElectronProfile) {
520 xMin = SimElectronProfile[0].X();
521 xMax = SimElectronProfile[nBin-1].X();
522 fElectron =
new TProfile(
"electron",
"electron profile",
523 nBin, xMin/
g*cm*cm, xMax/
g*cm*cm);
524 Xvert = xMin * absCosTheta;
525 if (Xvert < AtmDepthMin)
527 if (Xvert > AtmDepthMax)
529 HeightX = heightProfile.
Y(Xvert);
530 zMax = (HeightX - HeightObs) / absCosTheta;
531 Xvert = xMax * absCosTheta;
532 if (Xvert < AtmDepthMin)
534 if (Xvert > AtmDepthMax)
536 HeightX = heightProfile.
Y(Xvert);
537 zMin = (HeightX - HeightObs) / absCosTheta;
539 "electron profile vs z",
543 x != SimElectronProfile.
End(); ++x) {
547 Xvert = x->X() * absCosTheta;
548 if (Xvert < AtmDepthMin || Xvert > AtmDepthMax)
550 HeightX = heightProfile.
Y(Xvert);
551 z = (HeightX - HeightObs) / absCosTheta;
559 if (hasMuonProfile) {
561 xMin = SimMuonProfile[0].X();
562 xMax = SimMuonProfile[nBin-1].X();
563 fMuon =
new TProfile(
"muon",
"muon profile",
564 nBin, xMin/
g*cm*cm, xMax/
g*cm*cm);
565 Xvert = xMin * absCosTheta;
566 if (Xvert < AtmDepthMin)
568 if (Xvert > AtmDepthMax)
570 HeightX = heightProfile.
Y(Xvert);
571 zMax = (HeightX - HeightObs) / absCosTheta;
572 Xvert = xMax * absCosTheta;
573 if (Xvert < AtmDepthMin)
575 if (Xvert > AtmDepthMax)
577 HeightX = heightProfile.
Y(Xvert);
578 zMin = (HeightX - HeightObs) / absCosTheta;
579 fMuon_vs_z =
new TProfile(
"muon_vs_z",
"muon profile vs z",
583 x != SimMuonProfile.
End(); ++x) {
587 Xvert = x->X() * absCosTheta;
588 if (Xvert < AtmDepthMin || Xvert > AtmDepthMax)
590 HeightX = heightProfile.
Y(Xvert);
591 z = (HeightX - HeightObs) / absCosTheta;
599 if (hasdEdXProfile) {
601 xMin = SimdEdXProfile[0].X();
602 xMax = SimdEdXProfile[nBin-1].X();
603 fdEdX =
new TProfile(
"dEdX",
"dEdX profile", nBin, xMin/
g*
cm2, xMax/
g*cm2);
604 Xvert = xMin * absCosTheta;
605 if (Xvert < AtmDepthMin)
607 if (Xvert > AtmDepthMax)
609 HeightX = heightProfile.
Y(Xvert);
610 zMax = (HeightX - HeightObs) / absCosTheta;
611 Xvert = xMax * absCosTheta;
612 if (Xvert < AtmDepthMin)
614 if (Xvert > AtmDepthMax)
616 HeightX = heightProfile.
Y(Xvert);
617 zMin = (HeightX - HeightObs) / absCosTheta;
618 fdEdX_vs_z =
new TProfile(
"dEdX_vs_z",
"dEdX profile vs z",
622 x != SimdEdXProfile.
End(); ++x) {
626 Xvert = x->X() * absCosTheta;
627 if (Xvert < AtmDepthMin || Xvert > AtmDepthMax)
629 HeightX = heightProfile.
Y(Xvert);
630 z = (HeightX - HeightObs) / absCosTheta;
639 if (hasMuonProductionProfile) {
644 }
else if (hasMuonProfile) {
660 fdNdX =
new TProfile();
666 fMuon =
new TProfile();
675 fdEdX =
new TProfile();
681 fdNdz =
new TProfile();
724 if (hasMuonProductionProfile) {
727 INFO(
"TimeModel from MuonProduction Profile");
729 GetLogZdist(SimMuonProductionProfile, simCore, simAxis);
733 }
else if (hasMuonProfile) {
735 WARNING (
"TimeModel from Muon-Profile: NOT PROPERLY IMPLEMENTED YET");
744 ERROR(
"no muon profiles available, to init time model!");
751 INFO(
"TimeModel from parametrisation");
752 const double logE = log10(simEnergy/
eV);
757 lorenzoTimeModel->
Info();
764 const double XobsS1000 = XobsVert / absCosTheta;
773 if (XobsS1000 > ProfileMaxDepth) {
774 WARNING(
"Shower does not reach ground! Extrapolate profile!");
778 const double NmuLastPoint = SimMuonProfile[SimMuonProfile.
GetNPoints()-1].
Y();
779 const double depthLastPoint = SimMuonProfile[SimMuonProfile.
GetNPoints()-1].X()/
g*
cm2;
781 const double gammaFactor = 10;
787 dbg <<
" Nmu-profile (last point)= "<<NmuLastPoint
788 <<
" Depth (last point)= "<<depthLastPoint
789 <<
" distance (last point)= "<<distanceLastPoint
790 <<
" height needed= "<<HeightObs
791 <<
" gammaFactor= "<<gammaFactor
805 Nmu = SimMuonProfile.
Y(XobsS1000);
806 Ng = SimGammaProfile.
Y(XobsS1000);
807 Ne = SimElectronProfile.
Y(XobsS1000);
816 dbg <<
" ********* calculate S1000 ********** " << endl;
817 dbg <<
" Age " << Age <<
" rm " << Rm/
m
818 <<
" Ne " << Ne <<
" Ng " << Ng
819 <<
" Nmu " << Nmu <<
" XobsS1000 " << XobsS1000/
g*
cm*
cm;
831 dbg <<
" S1000 " << S1000 <<
" Energy/EeV " << simEnergy/
EeV << endl;
832 dbg <<
" ********* calculated S1000 ********** ";
837 int closestStationID = -1;
843 double closestStationDistance = 0;
848 const int tankID = iStation->GetId();
851 const Point& tankPos = iStation->GetPosition();
853 const double PosXinShower = tankPos.
GetX(ShowerCS);
854 const double PosYinShower = tankPos.
GetY(ShowerCS);
857 const double coreDistance =
sqrt(PosXinShower*PosXinShower +
858 PosYinShower*PosYinShower);
860 if (closestStationID < 0 || coreDistance < closestStationDistance) {
864 if (iStation->IsInAcquisition()) {
865 closestStationID = tankID;
866 closestStationDistance = coreDistance;
869 closestStationID = tankID;
870 closestStationDistance = coreDistance;
890 const int tankID = iStation->GetId();
897 ERROR(
"StationID occured twice in detector !!!!!! skipping !!!");
930 const Point& tankPos = iStation->GetPosition();
932 const double PosXinShower = tankPos.
GetX(ShowerCS);
933 const double PosYinShower = tankPos.
GetY(ShowerCS);
934 const double PosZinShower = tankPos.
GetZ(ShowerCS);
936 const double coreDistance =
sqrt(PosXinShower*PosXinShower + PosYinShower*PosYinShower);
943 const Point tankAtAxis(0,0, PosZinShower, ShowerCS);
945 const double tankOverSeaLevel =
948 const double tankAtAxisOverSeaLevel =
951 const Vector tankAtAxisToCore = tankAtAxis - simCore;
952 const double distanceTankAtAxisToCore = tankAtAxisToCore.
GetMag();
953 const double distanceFromCoreAtAxis = distanceTankAtAxisToCore *
954 (tankAtAxisToCore*simAxis < 0 ? 1 : -1);
962 dbg <<
" tank " << tankID
963 <<
" height@axis " << tankAtAxisOverSeaLevel
964 <<
" AtmMin " << atmDistanceMin
965 <<
" AtmMax " << atmDistanceMax;
970 bool flagAtmExceeded =
false;
972 if (distanceFromCoreAtAxis < atmDistanceMin ||
973 distanceFromCoreAtAxis > atmDistanceMax) {
978 dbg <<
" ATM EXCEEDED: "
979 <<
" TankR: " << coreDistance/
m
980 <<
" TankAtAxisOverSeaLevel: " << tankAtAxisOverSeaLevel/
m
981 <<
" DistanceAtAxisFromCore: " << distanceFromCoreAtAxis/
m
982 <<
" min " << atmDistanceMin <<
" " << atmDistanceMax;
989 flagAtmExceeded =
true;
994 xTank = slantDepthVsDistance.
Y(distanceFromCoreAtAxis);
998 const double tankRadius = iStation->GetRadius();
999 const double tankHeight = iStation->GetHeight();
1007 double Xobs = xTank;
1009 bool ShowerProfileRangeExceeded =
false;
1010 if (Xobs > ProfileMaxDepth) {
1012 ShowerProfileRangeExceeded =
true;
1019 dbg <<
" ShowerProfileRangeExceeded " << ShowerProfileRangeExceeded
1020 <<
" maxX " << ProfileMaxDepth/
g*
cm*
cm
1021 <<
" Xobs " << Xobs/
g*
cm*
cm
1023 <<
" " << SimMuonProfile[0].X()
1024 <<
" " << SimMuonProfile[SimMuonProfile.
GetNPoints()-1].X()
1025 <<
" " << SimMuonProfile[0].X()/
g*
cm2
1026 <<
" " << SimMuonProfile[SimMuonProfile.
GetNPoints()-1].X()/
g*
cm2;
1032 if (
fVerbosity > 1 && ShowerProfileRangeExceeded) {
1052 if (ShowerProfileRangeExceeded) {
1055 const double NmuLastPoint = SimMuonProfile[SimMuonProfile.
GetNPoints()-1].
Y();
1056 const double depthLastPoint = SimMuonProfile[SimMuonProfile.
GetNPoints()-1].X()/
g*
cm2;
1058 const double gammaFactor = 10;
1060 Nmu = NmuLastPoint *
1065 dbg <<
" Nmu-profile (last point)= " << NmuLastPoint
1066 <<
" Depth (last point)= " << depthLastPoint
1067 <<
" distance (last point)= " << distanceLastPoint
1068 <<
" distance needed at axis= " << distanceFromCoreAtAxis
1069 <<
" gammaFactor= " << gammaFactor
1070 <<
" --> Nmu= " << Nmu;
1083 Nmu = SimMuonProfile.
Y(Xobs);
1084 Ng = SimGammaProfile.
Y(Xobs);
1085 Ne = SimElectronProfile.
Y(Xobs);
1096 dbg <<
" Age " << Age <<
" rm " << Rm/
m
1097 <<
" Ne " << Ne <<
" Ng " << Ng
1098 <<
" Nmu " << Nmu <<
" Xtank " << Xobs/
g*
cm2
1099 <<
" Xmax " << Xmax/
g*
cm2
1100 <<
" S " << tankSignal;
1107 if (tankSignal < 0.01) {
1110 dbg <<
" tank " << tankID
1111 <<
" has signal < 0.01 (closestStation= " << closestStationID <<
") ";
1117 ostringstream infoString;
1118 infoString <<
"Forcing tank trigger for tank signal (previous) S=" << tankSignal <<
" set to S=5";
1127 INFO(
" setting to silent");
1141 msg <<
"Station " << tank.
GetId() <<
" already has SimData!";
1167 dbg <<
" p_trig " << p_trig;
1179 info <<
"tank id="<< tankID
1180 <<
" r=" << coreDistance/
m <<
"m"
1181 " S=" << tankSignal <<
"VEM"
1182 " p_trig=" << p_trig
1202 warn <<
"Shower profile range exceeded "
1203 "(" << (ShowerProfileRangeExceeded ?
"true" :
"false")
1205 << (flagAtmExceeded ?
"[ATM out of bound]" :
"")
1206 <<
" Station at X=" << xTank/
g*
cm2 <<
" g/cm2 "
1207 "(h=" << tankOverSeaLevel/
m <<
"m,"
1208 "r=" << coreDistance/
m <<
"m) "
1209 "but Profile ends at " << ProfileMaxDepth/
g*
cm2
1211 <<
"(Signal: " << tankSignal <<
", "
1212 "p_trig: " << p_trig <<
", "
1229 const double R = tankPos.
GetRho(ShowerCS);
1230 double Phi = tankPos.
GetPhi(ShowerCS);
1250 WARNING(
" TIME-MODEL: Muon-model timing for signal without muons !!! Use nMuon=1");
1262 static const double constK = 5.368e-5*
ns/(
m*
m);
1264 static const double SigmaT0 = 26.84*
ns;
1266 double sigmaTime = 0;
1268 sigmaTime = SigmaT0;
1270 sigmaTime =
sqrt(SigmaT0*SigmaT0 +
pow(constK*R*R*absCosTheta, 2));
1282 TriggerTime = stationTime;
1284 if (TriggerTime > stationTime)
1285 TriggerTime = stationTime;
1312 info <<
"tank id="<< tankID
1313 <<
" r=" << coreDistance/
m <<
"m"
1314 <<
" S=" << tankSignal <<
"VEM"
1315 <<
" p_trig=" << p_trig
1316 <<
" t=" << tankTime <<
"ns";
1317 if (tankID == closestStationID)
1318 info <<
" [closest]";
1320 info <<
" z_sh=" << PosZinShower/
m <<
"m"
1329 delete lorenzoTimeModel;
1333 info <<
"There have been " << nNotInDAQ <<
" stations not in DAQ accoring to T2 life file!";
1341 STrigger.
SetTime(TriggerTime);
1355 INFO(
" -------->noise ");
1359 int nSignalNoiseTank = 0;
1368 if (!iStation->IsInAcquisition()) {
1373 int tankID = iStation->GetId();
1377 double timeOffset = 0;
1383 if (
Noise(sEvent, TriggerTime, tankID, timeOffset, timeWindow))
1392 if (
true ==
false &&
1398 const double fadcTraceLength = iStation->GetFADCTraceLength() * iStation->GetFADCBinSize();
1399 timeWindow = fadcTraceLength;
1401 if (
Noise(sEvent, TriggerTime, tankID, timeOffset, timeWindow)) {
1410 if (
Noise(sEvent, TriggerTime, tankID, timeOffset, timeWindow))
1417 inf <<
" Number of noise stations: " << nNoiseTank;
1418 if (nSignalNoiseTank > 0) {
1419 inf <<
", of which " << nSignalNoiseTank <<
" tank" << (nSignalNoiseTank == 1 ?
"" :
"s")
1420 <<
" also contain" <<
" shower signal.";
1434 if (!station.HasRecData() || !station.GetRecData().GetTotalSignal())
1435 station.SetSilent();
1477 inf <<
"trying to use the NKG function outside valid range (age<=2.25): age= "<<s<<
" --> using constant age = 2.24";
1484 const double C = TMath::Gamma(4.5 - s) / (TMath::Gamma(s) * TMath::Gamma(4.5 - 2*s));
1485 const double rho = C * N/(2*
kPi*Rmoliere*Rmoliere) *
pow(R, s - 2) *
pow(1 + R, s - 4.5);
1494 double timeOffset,
double timeWindow)
1500 INFO(
" ++++++++++++++++++++== generate noise!! +++++++++++++++");
1530 const double timeOverThresholdRate = 1.6*
hertz;
1558 dbg <<
" noise stations: " << tankID <<
" signal: " << Signal <<
"VEM "
1575 if (r < NoiseEvents) {
1596 -TimeWindow, TimeWindow);
1606 static double Norm = 1.217e3;
1607 static double Mean = 4.087e-1;
1608 static double Sigma = 9.7614e-2;
1609 static double Const = 8.95;
1610 static double Slope = 5.37;
1611 static double JoiningPoint = Mean+2*
Sigma;
1612 static double Integral_expo = exp(Const - Slope*JoiningPoint) / Slope;
1613 static double Integral_gaus = Norm *
sqrt(
kPi*2) * Sigma * 0.975;
1614 static double Integral = Integral_expo + Integral_gaus;
1615 static double p_gaus = (Integral - Integral_expo) / Integral;
1627 }
while (log10VEM > JoiningPoint);
1634 double N = 1./(Slope) * exp(-Slope*JoiningPoint);
1635 log10VEM = log(r*N*(-Slope) + exp(-Slope*JoiningPoint)) / (-Slope);
1638 double Signal =
pow(10., log10VEM);
1640 Signal += OldSignal;
1645 if (OldTime>stationTime ||
1665 double cosTheta = cos(theta);
1666 double sinTheta = sin(theta);
1668 double UntilBottom = 0;
1670 UntilBottom = z / cos(theta);
1675 double UntilSide = 0;
1677 UntilSide = (tankRadius + r * cos(phi) -
1679 sqrt(tankRadius*tankRadius -
1680 r * r * sin(phi) * sin(phi) ))) / sin(theta);
1685 return min(UntilSide, UntilBottom);
1694 const double Rltp = 1;
1695 const double Wltp = 1;
1696 return 1 / (1 + exp((r - Rltp) / Wltp));
1710 const double a1 = 6.42522 - 1.53183 * Age;
1711 const double a2 = 168.168 - 42.1368 * Age;
1713 double F2max =
NerlingF2(Emin, a2, Age);
1729 E = exp(r1 * log (Emax+a1) + (1-r1) * log(Emin+a1)) - a1;
1738 }
while (accept/F2max < r2);
1745 dbg <<
" sample-E: "
1749 << E/
MeV <<
" " << Age <<
" " << N;
1764 return 1. / (E + a1);
1773 return 1 /
pow((E + a2), s);
1795 double atmDepthMin = distanceVsSlantDepth.
MinX();
1796 double atmDepthMax = distanceVsSlantDepth.
MaxX();
1798 vector <double> ValueZ;
1799 vector <double> ValuedNdZ;
1802 double dXslant =
abs(prof[1].X() - prof[0].X());
1804 for (
unsigned int iBin = 0; iBin < prof.
GetNPoints(); ++iBin) {
1806 double nDmu = prof [iBin].
Y();
1807 double xSlant = prof [iBin].X();
1809 double xSlantLow = xSlant-dXslant/2;
1810 double xSlantHigh = xSlant+dXslant/2;
1814 if (xSlantLow < atmDepthMin || xSlantHigh > atmDepthMax) {
1825 const double distanceLow = distanceVsSlantDepth.
Y(xSlantHigh);
1826 const double distanceHigh = distanceVsSlantDepth.
Y(xSlantLow);
1827 const double distance = distanceVsSlantDepth.
Y(xSlant);
1829 const double z = -distance;
1830 const double zLow = -distanceLow;
1831 const double zHigh = -distanceHigh;
1835 double dz =
abs(zHigh - zLow);
1853 double logz = log10(z);
1854 double dLogz = log10(dz);
1855 double dMuLogz = (nDmu*dXslant/dLogz) /
g*
cm*
cm *
m;
1859 ValueZ.insert(ValueZ.begin(), logz);
1860 ValuedNdZ.insert(ValuedNdZ.begin(), dMuLogz);
1889 const double cosTheta,
const double xobs)
1900 const double heightXobs = heightProfile.
Y(xobs);
1902 vector<double> valueZ;
1903 vector<double> valuedNdZ;
1905 const double atmDepthMin = depthProfile.
Y(depthProfile.
MaxX());
1906 const double atmDepthMax = depthProfile.
Y(depthProfile.
MinX());
1912 for (
unsigned int iBin = 0; iBin < muonProfile.
GetNPoints(); ++iBin) {
1914 const double nmu = muonProfile[iBin].
Y();
1915 const double xslant = muonProfile[iBin].X();
1916 const double xvert = xslant * cosTheta;
1918 if (xvert < atmDepthMin || xvert > atmDepthMax)
1921 const double heightX = heightProfile.
Y(xvert);
1922 const double z = (heightX - heightXobs) / cosTheta;
1939 const double dz = z - z_old;
1940 const double dN = nmu_old - nmu;
1941 const double zMean = 0.5*(z_old + z);
1947 valueZ.insert(valueZ.begin(), zMean);
1948 valuedNdZ.insert(valuedNdZ.begin(), dN/dz);
1974 const int nBoxCar = 5;
1975 for (
int i = 0; i < nPoints-nBoxCar; ++i) {
1980 for (
int iBoxCar = 0; iBoxCar < nBoxCar; ++iBoxCar) {
1982 int bin = nPoints - 1 - i - iBoxCar;
1983 value += profile[bin].
Y();
1992 maximumBin = nPoints - 1 - i;
1994 if (maximum < value) {
1996 maximumBin = nPoints - 1 - i;
2003 int startFitBin = maximumBin + int((nPoints - maximumBin) * 0.75);
2008 dbg <<
" profile fitting maxBin " << maximumBin
2009 <<
" startFitBin " << startFitBin
2010 <<
" nbins "<<nPoints;
2015 if (nPoints - startFitBin < 3) {
2018 dbg <<
" failed profile extrapolation!\n"
2019 " tried to fit from bin " << startFitBin <<
" to " << nPoints;
2033 for (
int i = startFitBin; i < nPoints; ++i) {
2035 const double value = log(profile[i].Y() / (dEdX ?
GeV/
g*
cm2 : 1));
2036 const double depth = profile[i].X() /
g*
cm2;
2037 const double wi = 1/(.1*value * .1*value);
2041 Sxx += wi * depth * depth;
2043 Sxy += wi * depth * value;
2047 const double det = S1*Sxx - Sx*Sx;
2049 const double a1 = (Sxx*Sy - Sx*Sxy) / det;
2050 const double a2 = (-Sx*Sy + S1*Sxy) / det;
2060 const double minX = profile.
MinX();
2061 const double maxX = profile.
MaxX()-50*
cm;
2063 const int nPoints = 10;
2064 const double lastPart = (maxX-minX) / 30;
2065 const double dX = lastPart / (nPoints-1);
2066 const double startX = maxX-lastPart;
2075 for (
int i = 0; i < nPoints; ++i) {
2077 const double x = startX + dX * i;
2078 const double value = log(profile.
Y(x)/
g*
cm2);
2079 const double wi = 1./(.1*value*.1*value);
2085 Sxy += wi * x * value;
2090 double D = S1*Sxx - Sx*Sx;
2092 double a1 = (Sxx*Sy - Sx * Sxy)/D;
2093 double a2 = (-Sx*Sy + S1*Sxy)/D;
2101 double tankRadius,
double tankHeight,
double Zenith,
2102 double Age,
double Rm,
2103 double Ne,
double Ng,
double Nmu,
2106 double cosTheta = cos (Zenith);
2107 double sinTheta = sin (Zenith);
2109 double tankProjTop =
kPi * tankRadius * tankRadius * cosTheta;
2110 double tankProjSide = tankHeight * 2.* tankRadius * sinTheta;
2111 double tankProjArea = tankProjTop + tankProjSide;
2119 double nElectrons = RhoElectrons * tankProjArea;
2120 double nGammas = RhoGammas * tankProjArea;
2121 double nMuons = RhoMuons * tankProjArea;
2125 dbg <<
" +++++++ calculating tank signal at age " << Age <<
" and zenith " << Zenith*180./3.1415 <<
"deg +++++++++++\n"
2126 " A " << tankProjArea/
m/
m <<
"\n"
2127 " coreDistance: " << coreDistance/
m <<
" E + G [cD/rm]: " << coreDistance/Rm <<
" mu [cD/scale]: " << coreDistance/
fMuonRScale <<
"\n"
2128 " Ne : " << Ne <<
" Ng: " << Ng <<
" Nmu: " << Nmu <<
"\n"
2129 " rho " << RhoElectrons <<
" " << RhoGammas <<
" " << RhoMuons <<
"\n"
2130 " nPart (no fluc) : " << nElectrons <<
" " << nGammas <<
" " << nMuons;
2146 dbg <<
" nPart " << nElectrons <<
" " << nGammas <<
" " << nMuons << endl;
2150 double nParticles = nElectrons + nGammas + nMuons;
2152 if (nParticles <= 1) {
2158 int nSample = (fluctuation ? std::min(
fNSample,
int(nMuons)) :
fNSample*10);
2160 double Weight = nMuons / double(nSample);
2161 for (
int iSample = 0; iSample < nSample; ++iSample) {
2168 if (p < tankProjTop/tankProjArea) {
2188 const double TrackLength =
TankIntersection(r, phi, z, Zenith, tankRadius);
2192 dbg <<
" muon track/m: " << TrackLength/
m;
2202 nSample = (fluctuation ? std::min(
fNSample,
int(nElectrons)) :
fNSample*10);
2204 double Weight = nElectrons/(double)nSample;
2205 for (
int iSample = 0; iSample < nSample; ++iSample) {
2208 static double Emin = 1e-2 *
MeV;
2209 static double Emax = 1e+5 *
MeV;
2220 double Weight = nGammas/(double)nSample;
2221 for (
int iSample = 0; iSample < nSample; ++iSample) {
2224 static double Emin = 1e-2 *
MeV;
2225 static double Emax = 1e+5 *
MeV;
2244 { 1.9, 2.2, 3.6, 5.1 },
2245 { 1.9, 3.0, 3.5, 4.8 },
2246 { 2.5, 3.3, 4.1, 5.1 },
2247 { 3.5, 3.8, 4.2, 5.4 },
2248 { 4.2, 4.8, 4.8, 5.0 }
2262 static double n = 2.8;
2283 dbg <<
" pT1: " << theta <<
" " << S1000 <<
" " << signal;
2289 for (thetaBin = 0; thetaBin < 4; ++thetaBin) {
2296 for (s1000Bin = 0; s1000Bin < 3; ++s1000Bin) {
2315 double S_half_1 = S_half_11 + (S_half_12 - S_half_11) * delta_s1000;
2316 double S_half_2 = S_half_21 + (S_half_22 - S_half_21) * delta_s1000;
2317 double S_half_1_error = S_half_error_11 + (S_half_error_12 - S_half_error_11) * delta_s1000;
2318 double S_half_2_error = S_half_error_21 + (S_half_error_22 - S_half_error_21) * delta_s1000;
2321 double S_half = S_half_1 + (S_half_2 - S_half_1) * delta_theta;
2322 double S_half_error = S_half_1_error + (S_half_2_error - S_half_1_error) * delta_theta;
2327 dbg <<
" S_0.5 " << S_half <<
" " << S_half_error;
2332 double p =
pow(signal, n);
2333 p /= (p +
pow(S_half, n));
2341 const double switchTriggerGPS = 795.3e6;
bool HasDirection() const
Check initialization of shower geometry.
constexpr double kMuonLifetime
Class to access station level reconstructed data.
utl::CoordinateSystemPtr GetLocalCoordinateSystem() const
Get the Auger coordinate system associated to the shower core position.
int GetPrimaryParticle() const
Get the type of the shower primary particle.
unsigned int GetNPoints() const
Station Level Simulated Data
StationIterator StationsEnd()
End of all stations.
void SetTotalSignal(const double signal, const double sErr=0)
Total integrated signal in VEM unit, averaged over pmts.
int GetId() const
Get the station Id.
const utl::TimeStamp & GetTimeStamp() const
Get the TimeStamp of the absolute shower core-time.
static double fgTriggerThetaBins[5]
bool HasStation(const int stationId) const
Check whether station exists.
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
void InitSlantProfileModel(const utl::Point &core, const utl::Vector &dir, const double deltaX) const
utl::TabulatedFunction CalculateLogZdist(const utl::TabulatedFunction &MuonProfile, double cosTheta, double XobsVert)
Report success to RunController.
void MakeSimData()
Make station simulated data object.
RandomEngineType & GetEngine()
double SampleEnergy(double Emin, double Emax, double Age)
const evt::VGaisserHillasParameter & GetGHParameters() const
Get the Gaisser-Hillas parameters of the shower.
Interface class to access to the SD part of an event.
FitParam FitDecay(const utl::TabulatedFunction &prof, bool dEdX=false)
void SetOffsetMicroSecond(const int offset)
Skip remaining modules in the current loop and continue with next iteration of the loop...
Class to hold collection (x,y) points and provide interpolation between them.
bool HasTriggerData() const
Check whether trigger data object exists.
void SetTime(const utl::TimeStamp &time)
Set time of the trigger.
void SetCandidate()
Set candidate station flag.
bool HasSimShower() const
EventTrigger & GetTrigger()
Get the object with central trigger data, throw if n.a.
const atm::ProfileResult & EvaluateDistanceVsSlantDepth() const
Table of distance as a function of slant depth.
sevt::StationRecData & GetRecData()
Get station level reconstructed data.
#define INFO(message)
Macro for logging informational messages.
static double fgTriggerS1000Bins[4]
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
double pow(const double x, const unsigned int i)
double T1TriggerProbability(double signal, double S1000, double theta)
std::string GetVersionInfo(const VersionInfoType v) const
Retrieve different sorts of module version info.
bool Noise(sevt::SEvent &sevent, const utl::TimeStamp &T0, int TankID, double TimeOffset, double TimeWindow)
void MakeTriggerData()
Make trigger data object.
void SetSimulatorSignature(const std::string &name)
Set name of the tank simulator module used to simulate this station.
fwk::VModule::ResultFlag Run(evt::Event &event)
Run: invoked once per event.
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.
double CalculateTankSignal(double CoreDistance, double TankRadius, double TankHeight, double Zenith, double Age, double Rm, double Ne, double Ng, double Nmu, bool fluctuations=true)
Interface class to access Shower Simulated parameters.
double TankIntersection(double r, double phi, double z, double theta, double TankRadius)
const atm::Atmosphere & GetAtmosphere() const
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
static double kMeterPerVEM
Class representing a document branch.
bool fMuonProductionHeightFromProfile
class to hold data at Station level
fwk::VModule::ResultFlag Init()
Initialize: invoked at beginning of run (NOT beginning of event)
void SetLowGainSaturation(const bool sat=true)
double GenerateNoiseStation(sevt::Station &tank, const utl::TimeStamp &T0, double TimeOffset, double TimeWindow)
Reference ellipsoids for UTM transformations.
bool HasSimData() const
Check whether station simulated data exists.
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.
double GetX(const CoordinateSystemPtr &coordinateSystem) const
double MoliereRadius(double temperature, double pressure, const double cosTheta)
The Moliere Radius (2 radiation length above obs-level, GAP-1998-002)
Interface class to access the Event Trigger (T3)
Class describing the Atmospheric profile.
double abs(const SVector< n, T > &v)
double GetTotalSignal() const
Total integrated signal in VEM unit, averaged over pmts.
const utl::Point & GetPosition() const
Get the position of the shower core.
Top of the hierarchy of the detector description interface.
const sdet::SDetector & GetSDetector() const
bool HasTrigger() const
check whether the central trigger object exists
void MakeTrigger()
Create the central trigger object.
Triple PointToLatitudeLongitudeHeight(const Point &thePoint) const
Convert Point to Lat/Long/Height.
StationIterator StationsEnd() const
End of the collection of pointers to commissioned stations.
const atm::ProfileResult & EvaluateDepthVsHeight() const
Tabulated function giving Y=depth as a function of X=height.
double NerlingF2(double E, double a2, double s)
double GetEnergy() const
Get the energy of the shower primary particle.
StationIterator StationsBegin() const
Beginning of the collection of pointers to commissioned stations.
double GetFirstTime(const int n=1)
void SetPlaneFrontTime(const utl::TimeStamp &time)
Set shower front plane arrival time.
void MakeStation(const int stationId)
make a station with specifying Id, throw if invalid stationId
#define WARNING(message)
Macro for logging warning messages.
void GetData(bool &b) const
Overloads of the GetData member template function.
utl::RandomEngine & fRandomEngine
for CLHEP random nubers
double LTP(double r, double theta, double energy)
double Sigma(const double energy, const double massNumber, const HadronicInteractionModel hadModel)
fwk::VModule::ResultFlag Finish()
Finish: invoked at end of the run (NOT end of the event)
static double kTrackPerGEV
Station & GetStation(const int stationId)
retrieve station by id throw utl::NonExistentComponentException if n.a.
std::map< evt::ShowerSimData::ProfileType, FitParam > fProfileExtrapolation
double GetInterval() const
Get the time interval as a double (in Auger base units)
double GetRho(const CoordinateSystemPtr &coordinateSystem) const
radius r in cylindrical coordinates (distance to z axis)
void SetSignalStartTime(const utl::TimeStamp time)
Start time of the signal.
void MakeRecData()
Make station reconstructed data object.
double GetY(const CoordinateSystemPtr &coordinateSystem) const
constexpr double kSpeedOfLight
A TimeInterval is used to represent time elapsed between two events.
double MinX() const
Return the minimum value for X (ordinate) stored in the profile.
Algorithm GetAlgorithm() const
ResultFlag
Flag returned by module methods to the RunController.
static double fgTriggerPropShalf[5][4]
unsigned long GetGPSSecond() const
GPS second.
bool HasRecData() const
Check whether station reconstructed data exists.
double ShowerAge(const double slantDepth, const double showerMax)
General definition of shower age.
Collection of pre-defined random engines.
Station Trigger Data description
StationIterator StationsBegin()
Beginning of all stations.
bool HasGHParameters() const
Check initialization of the Gaisser-Hillas parameters.
TProfile * fElectron_vs_z
void SetWindowMicroSecond(const int window)
execption handling for calculation/access for inclined atmosphere model
void SetAlgorithm(const std::string &algo)
Set algorithm of the trigger.
Detector description interface for SDetector-related data.
Report failure to RunController, causing RunController to terminate execution.
sevt::Header & GetHeader()
Main configuration utility.
sevt::StationSimData & GetSimData()
Get simulated data at station level.
utl::CoordinateSystemPtr Get(const std::string &id)
Get a well-known Coordinate System.
const atm::ProfileResult & EvaluateHeightVsDepth() const
Tabulated function giving Y=height as a function of X=depth.
static double fgTriggerPropShalfError[5][4]
double NerlingF1(double E, double a1)
void SetAlgorithm(const Algorithm algo)
sevt::StationTriggerData & GetTriggerData()
Get Trigger data for the station.
double Mean(const std::vector< double > &v)
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
double Y(const double x) const
Get or interpolate the Y value that corresponds to parameter x.
void SetHighGainSaturation(const bool sat=true)
const atm::ProfileResult & EvaluateSlantDepthVsDistance() const
#define ERROR(message)
Macro for logging error messages.
bool IsNoise(double TimeWindow)
constexpr double microsecond
FitParam FitAtmosphere(const atm::ProfileResult &prof)
double NKG(double N, double Rm, double R, double s)
void SetErrorCode(const int errorCode)
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)
utl::CoordinateSystemPtr GetShowerCoordinateSystem() const
const atm::ProfileResult & EvaluateTemperatureVsHeight() const
Tabulated function giving Y=temperature as a function of X=height.
double MaxX() const
Return the maximum value for X (ordinate) stored in the profile.
double GetCDASTriggerTimeWindow(const utl::TimeStamp &time)
utl::TabulatedFunction GetLogZdist(const utl::TabulatedFunction &prof, const utl::Point &core, const utl::Vector &axis)
const utl::TabulatedFunction & GetLongitudinalProfile(const ProfileType type=eCharged) const
Get the longitudinal charge profile of the shower.
bool fForceClosestTankToTrigger
double fNoiseRatePerStation
FitParam fSlantDepthExtrapolation
void SetCoordinates(const double r, const double zeta)