SdSimpleSim.cc
Go to the documentation of this file.
1 
9 /*
10  StationTrigger ErrorCode
11  0 ok
12  2 no-data, but station ok
13 
14  53 strange
15  56 strange
16 */
17 
18 #include <fwk/CentralConfig.h>
19 #include <fwk/CoordinateSystemRegistry.h>
20 #include <fwk/RandomEngineRegistry.h>
21 
22 #include <evt/Event.h>
23 #include <evt/ShowerSimData.h>
24 
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>
32 
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>
42 
43 #include <det/Detector.h>
44 #include <sdet/SDetector.h>
45 
46 #include <atm/Atmosphere.h>
47 #include <atm/ProfileResult.h>
48 #include <atm/InclinedAtmosphericProfile.h>
49 
50 #include "SdSimpleSim.h"
51 #include "MuonTimeModel.h"
52 
53 #include <CLHEP/Random/RandPoisson.h>
54 #include <CLHEP/Random/Randomize.h>
55 #include <CLHEP/Random/RandGauss.h>
56 #include <CLHEP/Random/RandFlat.h>
57 
58 #include <TMath.h>
59 #include <TFile.h>
60 #include <TTree.h>
61 #include <TH1F.h>
62 #include <TProfile.h>
63 
64 #include <boost/range/iterator_range.hpp>
65 
66 #include <iostream>
67 
68 using CLHEP::RandGauss;
69 using CLHEP::RandFlat;
70 using CLHEP::RandPoisson;
71 
72 using namespace std;
73 using namespace evt;
74 using namespace fwk;
75 using namespace utl;
76 using namespace atm;
77 using namespace SdSimpleSimKG;
78 
79 
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;
84 
85 //
86 static double kMeterPerVEM = 1.2*meter; // [m/VEM]
87 static double kTrackPerGEV = 5.25*meter/GeV; //(see E. Zas, Malargue Nov 04)
88 //static double MeanEnergy = 25.*MeV; // e+- / gammas
89 // 240.MeV v. muon dE (1.2m) 0.240GeV/1.2m -> 5m/GeV
90 
91 
92 SdSimpleSim::SdSimpleSim() :
93  fRandomEngine(RandomEngineRegistry::GetInstance().Get(RandomEngineRegistry::ePhysics)),
94  fSdId(0),
95  // from analysis of run sd_2004_10_16_01h51.root
96  // per definition the T1 rate is about 100-110Hz
97  fNoiseRatePerStation(1.0065346445791242e+02 * hertz)
98 { }
99 
100 
103 {
104  CentralConfig* const cc = CentralConfig::GetInstance();
105  Branch topB = cc->GetTopBranch("SdSimpleSim");
106  if (!topB) {
107  ERROR("Could not find branch SdSimpleSim");
108  return eFailure;
109  }
110 
111  fSdId = 0;
112  topB.GetChild("verbosity").GetData(fVerbosity);
113 
114  topB.GetChild("useT2LifeTime").GetData(fUseT2LifeTime);
115  if (fUseT2LifeTime) {
116  INFO("Using T2 life manager for SD station status.");
117  }
118 
119  topB.GetChild("noise").GetData(fNoise);
120  topB.GetChild("MuonProductionHeightFromProfile").GetData(fMuonProductionHeightFromProfile);
121  topB.GetChild("n_sample").GetData(fNSample);
122  topB.GetChild("LateralCut").GetData(fLateralCut);
123  topB.GetChild("forceClosestTankToTrigger").GetData(fForceClosestTankToTrigger);
124  topB.GetChild("onlyClosestTank").GetData(fOnlyClosestTank);
125  topB.GetChild("planeShowerFront").GetData(fPlaneFront);
126  topB.GetChild("MuonRScale").GetData(fMuonRScale);
127  topB.GetChild("em_age_fact").GetData(fEMAgeFactor);
128 
129  // --- optional stuff ----------------------------
130 
131  Branch TMSB = topB.GetChild("TimeModelStat");
132  if (TMSB) {
133  INFO("Write time model statistics to root file.");
134 
135  string FileName;
136  TMSB.GetData(FileName);
137 
138  TFile* const StatFile = TFile::Open(FileName.c_str(), "recreate");
139  StatFile->cd();
140 
141  fLorenzo_vs_X = 0;
142  fdNdX = 0;
143  fCharged = 0;
144  fMuon = 0;
145  fElectron = 0;
146  fGamma = 0;
147  fdEdX = 0;
148  fLorenzo = 0;
149  fdNdz = 0;
150  fCharged_vs_z = 0;
151  fMuon_vs_z = 0;
152  fElectron_vs_z = 0;
153  fGamma_vs_z = 0;
154  fdEdX_vs_z = 0;
155 
156  fStatTree = new TTree("stat", "time model statistics");
157  fStatTree->Branch("Lorenzo_vs_X", "TProfile", &fLorenzo_vs_X, 32000, 0);
158  fStatTree->Branch("dNdX", "TProfile", &fdNdX, 32000, 0);
159  fStatTree->Branch("Charged", "TProfile", &fCharged, 32000, 0);
160  fStatTree->Branch("Gamma", "TProfile", &fGamma, 32000, 0);
161  fStatTree->Branch("Electron", &fElectron, 32000, 0);
162  fStatTree->Branch("Muon", "TProfile", &fMuon, 32000, 0);
163  fStatTree->Branch("dEdX", "TProfile", &fdEdX, 32000, 0);
164  fStatTree->Branch("Lorenzo", "TProfile", &fLorenzo, 32000, 0);
165  fStatTree->Branch("dNdz", "TProfile", &fdNdz, 32000, 0);
166  fStatTree->Branch("Charged_vs_z", "TProfile", &fCharged_vs_z, 32000, 0);
167  fStatTree->Branch("Gamma_vs_z", "TProfile", &fGamma_vs_z, 32000, 0);
168  fStatTree->Branch("Electron_vs_z", &fElectron_vs_z, 32000, 0);
169  fStatTree->Branch("Muon_vs_z", "TProfile", &fMuon_vs_z, 32000, 0);
170  fStatTree->Branch("dEdX_vs_z", "TProfile", &fdEdX_vs_z, 32000, 0);
171 
172  } else {
173 
174  fStatTree = 0;
175 
176  }
177 
178  // info output
179  ostringstream info;
180  info << " Version: "
181  << GetVersionInfo(VModule::eRevisionNumber) << "\n"
182  " Parameters:\n"
183  " verbosity: " << fVerbosity << "\n"
184  " use T2 lift time: " << fUseT2LifeTime << "\n"
185  " generate noise: " << fNoise << "\n"
186  " plane shower front: " << fPlaneFront << "\n"
187  " muon prod. profile: " << fMuonProductionHeightFromProfile << "\n"
188  " max no. samplings: " << fNSample << "\n"
189  " lateral cut: " << fLateralCut/km << "km\n"
190  " force closest tank: " << fForceClosestTankToTrigger << "\n"
191  " only closeset tank: " << fOnlyClosestTank << "\n"
192  " muon radial scale: " << fMuonRScale/m << "m\n"
193  " e.m. age factor: " << fEMAgeFactor << "\n";
194  INFO(info);
195 
196  return eSuccess;
197 }
198 
199 
202 {
203  // check event structure
204  if (!event.HasSimShower())
205  return eContinueLoop;
206 
207  const evt::ShowerSimData& SimShower = event.GetSimShower();
208 
209  if (!SimShower.HasDirection())
210  return eContinueLoop;
211 
212  if (!SimShower.HasPosition())
213  return eContinueLoop;
214 
215  if (!SimShower.HasLongitudinalProfile())
216  return eContinueLoop;
217 
218  if (!SimShower.HasGHParameters())
219  return eContinueLoop;
220 
221  const bool hasMuonProfile =
223 
224  const bool hasMuonProductionProfile =
225  SimShower.HasLongitudinalProfile(ShowerSimData::eMuonProduction);
226 
227  const bool hasGammaProfile =
229 
230  const bool hasElectronProfile =
232 
233  const bool hasdEdXProfile =
234  SimShower.HasLongitudinalProfile(ShowerSimData::eEnergyDeposit);
235 
236  if (!hasMuonProfile || !hasGammaProfile || !hasElectronProfile) {
237  ERROR("Input file not suitable for SdSimpleSim");
238  return eContinueLoop;
239  }
240 
241  if (!hasMuonProductionProfile && fMuonProductionHeightFromProfile) {
242  ERROR("Cannot use MuonProductionHeight from simulation");
243  return eContinueLoop;
244  }
245 
246  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
247  // extrapolate CONEX profiles
248  // assume exponential decay after the CONEX profile ends !
249  // fit the decay after Xmax
251  FitParam fitMuonProd;
252  if (hasMuonProductionProfile)
253  fitMuonProd = FitDecay(SimShower.GetLongitudinalProfile(ShowerSimData::eMuonProduction));
256  FitParam fitdEdX = FitDecay(SimShower.GetLongitudinalProfile(ShowerSimData::eEnergyDeposit), true);
258  fProfileExtrapolation[ShowerSimData::eMuonProduction] = fitMuonProd;
259  fProfileExtrapolation[ShowerSimData::ePhoton] = fitGamma;
260  fProfileExtrapolation[ShowerSimData::eElectron] = fitElectron;
261  fProfileExtrapolation[ShowerSimData::eEnergyDeposit] = fitdEdX;
262  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
263 
264  // make new time
265  const utl::TimeStamp& coreTime = SimShower.GetTimeStamp();
266  utl::TimeStamp TriggerTime = coreTime;
267  bool First = true;
268 
269  // get/create the sd-event
270  if (!event.HasSEvent())
271  event.MakeSEvent();
272  sevt::SEvent& sEvent = event.GetSEvent();
273  sevt::Header& sEventHeader = sEvent.GetHeader();
274  sEventHeader.SetTime(coreTime);
275  sEventHeader.SetId(++fSdId);
276 
277  // get the detector definitions
278  det::Detector& Det = det::Detector::GetInstance();
279  const sdet::SDetector& SDet = Det.GetSDetector();
280  const ReferenceEllipsoid& wgs84 = ReferenceEllipsoid::GetWGS84();
281 
282  //const ProfileResult& heightVsSlantDepth = Det.GetAtmosphere().EvaluateHeightVsSlantDepth();
283  //const ProfileResult& distanceVsHeight = Det.GetAtmosphere().EvaluateDistanceVsHeight();
284 
285  // get the simulated shower info
286  double Xmax = SimShower.GetGHParameters().GetXMax();
287  float simEnergy = SimShower.GetEnergy();
288  int simPrimary = SimShower.GetPrimaryParticle();
289 
290  if (fVerbosity > 3) {
291  ostringstream dbg;
292  dbg << " Sim-Parameters: Xmax= "<<Xmax/g*cm2;
293  INFO(dbg);
294  }
295 
296  const utl::Vector& simAxis = SimShower.GetDirection();
297  const utl::Point& simCore = SimShower.GetPosition();
298  const utl::TabulatedFunction& SimProfile = SimShower.GetLongitudinalProfile();
299  const utl::CoordinateSystemPtr& ShowerCS = SimShower.GetShowerCoordinateSystem();
300 
301  const CoordinateSystemPtr localCS = SimShower.GetLocalCoordinateSystem();
302  const double Zenith = (-SimShower.GetDirection()).GetTheta(localCS);
303 
304  const double cosTheta = cos(Zenith);
305  const double absCosTheta = std::fabs(cosTheta);
306  //double sinTheta = sin(Zenith);
307 
308  // ------- if inclined atmosphere was not initialized before, do it here ---------
309  try {
312  Det.GetAtmosphere().InitSlantProfileModel(simCore, -simAxis, 5.*g/cm2);
313  }
314  // -------------------------------------------------------------------------------
315 
316  const atm::ProfileResult depthProfile = Det.GetAtmosphere().EvaluateDepthVsHeight();
317 
318  const atm::ProfileResult temperatureProfile = Det.GetAtmosphere().EvaluateTemperatureVsHeight();
319 
320  const atm::ProfileResult heightProfile = Det.GetAtmosphere().EvaluateHeightVsDepth();
321 
322  // const ProfileResult& slantDepthVsHeight =
323  const ProfileResult& slantDepthVsDistance = Det.GetAtmosphere().EvaluateSlantDepthVsDistance();
324 
325  // +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
326  // interpolate Atmosphere
327  // assume exponential increase of slant depth with decreasing height
328  fSlantDepthExtrapolation = FitAtmosphere(slantDepthVsDistance);
329  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
330 
331  /*
332  double showerXstart = (SimShower.GetFluorescencePhotons(0))[0].X();
333 
334  // find the part, that was emitting (fluorescence) light
335  double InitialHeight = heightProfile.Y(showerXstart*cosTheta);
336 
337  const utl::Point showerStart = simCore +
338  simAxis * InitialHeight/simAxis.GetZ(siteCS);
339  */
340 
341  const utl::TabulatedFunction& SimMuonProfile =
343 
344  const utl::TabulatedFunction& SimGammaProfile =
346 
347  const utl::TabulatedFunction SimElectronProfile =
349 
350  utl::TabulatedFunction SimMuonProductionProfile;
351  if (hasMuonProductionProfile && fMuonProductionHeightFromProfile)
352  SimMuonProductionProfile = SimShower.GetLongitudinalProfile(ShowerSimData::eMuonProduction);
353  else {
354  if (!fPlaneFront)
355  ERROR("No muon production profile !!!!!!!!!");
356  }
357 
358  // just for debug plottings -------------------
359  utl::TabulatedFunction SimdEdXProfile;
360  if (hasdEdXProfile)
361  SimdEdXProfile =
362  SimShower.GetLongitudinalProfile(ShowerSimData::eEnergyDeposit);
363  // --------------------------------------------
364 
365  // Maximum profile slant-depth
366  double ProfileMaxDepth = SimProfile[SimProfile. GetNPoints() - 1].X();
367 
368  // ---------INFO-----------
369  if (fVerbosity > 3) {
370  ostringstream dbg;
371  dbg << " max prof depth " << ProfileMaxDepth/g*cm*cm
372  << " " << SimMuonProfile[0].X()/g*cm2
373  << " " << SimMuonProfile[SimMuonProfile.GetNPoints()-1].X()/g*cm2;
374  INFO(dbg);
375  }
376  // --------------------
377 
378  // calculate
379  const double HeightObs = wgs84.PointToLatitudeLongitudeHeight(simCore).get<2>();
380 
381  // atmospheric parameters
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) :
388  AtmDepthMax;
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;
393 
394  int lorenzoPrimary = -1;
395  if (!fPlaneFront) {
396  switch (simPrimary) {
398  lorenzoPrimary = 0;
399  break;
401  lorenzoPrimary = 1;
402  break;
404  lorenzoPrimary = 2;
405  break;
406  default:
407  ERROR("Unknown lorenzoPrimary!");
408  return eFailure;
409  break;
410  }
411  }
412 
413  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
414  if (fStatTree) {
415 
416  INFO(" STAT TREE ");
417 
418  fLorenzo_vs_X = 0;
419  fdNdX = 0;
420  fCharged = 0;
421  fMuon = 0;
422  fElectron = 0;
423  fGamma = 0;
424  fdEdX = 0;
425  fLorenzo = 0;
426  fdNdz = 0;
427  fCharged_vs_z = 0;
428  fMuon_vs_z = 0;
429  fElectron_vs_z = 0;
430  fGamma_vs_z = 0;
431  fdEdX_vs_z = 0;
432 
433  int nBin;
434  double xMin, xMax;
435  double zMin, zMax;
436  double Xvert, HeightX, z;
437 
438  // charged
439  nBin = SimProfile.GetNPoints();
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)
446  Xvert = AtmDepthMin;
447  if (Xvert > AtmDepthMax)
448  Xvert = AtmDepthMax;
449  HeightX = heightProfile.Y(Xvert);
450  zMax = (HeightX - HeightObs) / absCosTheta;
451  Xvert = xMax*absCosTheta;
452  if (Xvert < AtmDepthMin)
453  Xvert = AtmDepthMin;
454  if (Xvert > AtmDepthMax)
455  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",
459  nBin, zMin/meter, zMax/meter);
460 
461  for (TabulatedFunction::ConstIterator iBin = SimProfile.Begin();
462  iBin != SimProfile.End(); ++iBin) {
463 
464  fCharged->Fill(iBin->X()/g*cm2, iBin->Y());
465 
466  Xvert = iBin->X() * absCosTheta;
467  if (Xvert < AtmDepthMin || Xvert > AtmDepthMax)
468  continue;
469  HeightX = heightProfile.Y(Xvert);
470  z = (HeightX - HeightObs) / absCosTheta;
471 
472  fCharged_vs_z->Fill(z/meter, iBin->Y());
473 
474  }
475 
476  // gammas
477  if (hasGammaProfile) {
478  nBin = SimGammaProfile.GetNPoints();
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)
485  Xvert = AtmDepthMin;
486  if (Xvert > AtmDepthMax)
487  Xvert = AtmDepthMax;
488  HeightX = heightProfile.Y(Xvert);
489  zMax = (HeightX - HeightObs) / absCosTheta;
490  Xvert = xMax * absCosTheta;
491  if (Xvert < AtmDepthMin)
492  Xvert = AtmDepthMin;
493  if (Xvert > AtmDepthMax)
494  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",
498  nBin, zMin/meter, zMax/meter);
499 
500  for (utl::TabulatedFunction::ConstIterator x = SimGammaProfile.Begin();
501  x != SimGammaProfile.End(); ++x) {
502 
503  fGamma->Fill(x->X()/g*cm2, x->Y());
504 
505  Xvert = x->X() * absCosTheta;
506  if (Xvert < AtmDepthMin || Xvert > AtmDepthMax)
507  continue;
508  HeightX = heightProfile.Y(Xvert);
509  z = (HeightX - HeightObs) / absCosTheta;
510 
511  fGamma_vs_z->Fill(z/meter, x->Y());
512 
513  }
514  }
515 
516 
517  // electrons
518  if (hasElectronProfile) {
519  nBin = SimElectronProfile.GetNPoints();
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)
526  Xvert = AtmDepthMin;
527  if (Xvert > AtmDepthMax)
528  Xvert = AtmDepthMax;
529  HeightX = heightProfile.Y(Xvert);
530  zMax = (HeightX - HeightObs) / absCosTheta;
531  Xvert = xMax * absCosTheta;
532  if (Xvert < AtmDepthMin)
533  Xvert = AtmDepthMin;
534  if (Xvert > AtmDepthMax)
535  Xvert = AtmDepthMax;
536  HeightX = heightProfile.Y(Xvert);
537  zMin = (HeightX - HeightObs) / absCosTheta;
538  fElectron_vs_z = new TProfile("electron_vs_z",
539  "electron profile vs z",
540  nBin, zMin/meter, zMax/meter);
541 
542  for (utl::TabulatedFunction::ConstIterator x = SimElectronProfile.Begin();
543  x != SimElectronProfile.End(); ++x) {
544 
545  fElectron->Fill(x->X()/g*cm2, x->Y());
546 
547  Xvert = x->X() * absCosTheta;
548  if (Xvert < AtmDepthMin || Xvert > AtmDepthMax)
549  continue;
550  HeightX = heightProfile.Y(Xvert);
551  z = (HeightX - HeightObs) / absCosTheta;
552 
553  fElectron_vs_z->Fill(z/meter, x->Y());
554 
555  }
556  }
557 
558  // muons
559  if (hasMuonProfile) {
560  nBin = SimMuonProfile.GetNPoints();
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)
567  Xvert = AtmDepthMin;
568  if (Xvert > AtmDepthMax)
569  Xvert = AtmDepthMax;
570  HeightX = heightProfile.Y(Xvert);
571  zMax = (HeightX - HeightObs) / absCosTheta;
572  Xvert = xMax * absCosTheta;
573  if (Xvert < AtmDepthMin)
574  Xvert = AtmDepthMin;
575  if (Xvert > AtmDepthMax)
576  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",
580  nBin, zMin/meter, zMax/meter);
581 
582  for (utl::TabulatedFunction::ConstIterator x = SimMuonProfile.Begin();
583  x != SimMuonProfile.End(); ++x) {
584 
585  fMuon->Fill(x->X()/g*cm2, x->Y());
586 
587  Xvert = x->X() * absCosTheta;
588  if (Xvert < AtmDepthMin || Xvert > AtmDepthMax)
589  continue;
590  HeightX = heightProfile.Y(Xvert);
591  z = (HeightX - HeightObs) / absCosTheta;
592 
593  fMuon_vs_z->Fill(z/meter, x->Y());
594 
595  }
596  }
597 
598  // dEdXs
599  if (hasdEdXProfile) {
600  nBin = SimdEdXProfile.GetNPoints();
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)
606  Xvert = AtmDepthMin;
607  if (Xvert > AtmDepthMax)
608  Xvert = AtmDepthMax;
609  HeightX = heightProfile.Y(Xvert);
610  zMax = (HeightX - HeightObs) / absCosTheta;
611  Xvert = xMax * absCosTheta;
612  if (Xvert < AtmDepthMin)
613  Xvert = AtmDepthMin;
614  if (Xvert > AtmDepthMax)
615  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",
619  nBin, zMin/meter, zMax/meter);
620 
621  for (utl::TabulatedFunction::Iterator x = SimdEdXProfile.Begin();
622  x != SimdEdXProfile.End(); ++x) {
623 
624  fdEdX->Fill(x->X()/g*cm2, x->Y());
625 
626  Xvert = x->X() * absCosTheta;
627  if (Xvert < AtmDepthMin || Xvert > AtmDepthMax)
628  continue;
629  HeightX = heightProfile.Y(Xvert);
630  z = (HeightX - HeightObs) / absCosTheta;
631 
632  fdEdX_vs_z->Fill(z/meter, x->Y());
633 
634  }
635  }
636 
637 #if 0
638  // Lorenzos TimeModel -------------------------
639  if (hasMuonProductionProfile) {
640  /*TimeModel tmpModel(Zenith/deg, SimMuonProductionProfile,
641  XobsVert, ShowerSimData::eMuonProduction);
642  fdNdz = tmpModel.Get_dNdz_FromProfile();
643  fdNdX = tmpModel.Get_dNdX_FromProfile(absCosTheta, HeightObs);*/
644  } else if (hasMuonProfile) {
645  /*TimeModel tmpModel(Zenith/deg, SimMuonProfile, XobsVert,
646  ShowerSimData::eMuon);
647  fdNdz = tmpModel.Get_dNdz_FromProfile();
648  fdNdX = tmpModel.Get_dNdX_FromProfile(absCosTheta, HeightObs);*/
649  }
650 
651  /*TimeModel tmpModel(Zenith/deg, lorenzoPrimary);
652  fLorenzo = tmpModel.Get_dNdz(zMin, zMax, nBin);
653  fLorenzo_vs_X = tmpModel.Get_dNdX(zMin, zMax, nBin, absCosTheta, HeightObs);*/
654 #endif
655 
656  if (fLorenzo_vs_X == 0)
657  fLorenzo_vs_X = new TProfile();
658 
659  if (fdNdX == 0)
660  fdNdX = new TProfile();
661 
662  if (fCharged == 0)
663  fCharged = new TProfile();
664 
665  if (fMuon == 0)
666  fMuon = new TProfile();
667 
668  if (fElectron == 0)
669  fElectron = new TProfile();
670 
671  if (fGamma == 0)
672  fGamma = new TProfile();
673 
674  if (fdEdX == 0)
675  fdEdX = new TProfile();
676 
677  if (fLorenzo == 0)
678  fLorenzo = new TProfile();
679 
680  if (fdNdz == 0)
681  fdNdz = new TProfile();
682 
683  if (fCharged_vs_z == 0)
684  fCharged_vs_z = new TProfile();
685 
686  if (fMuon_vs_z == 0)
687  fMuon_vs_z = new TProfile();
688 
689  if (fElectron_vs_z == 0)
690  fElectron_vs_z = new TProfile();
691 
692  if (fGamma_vs_z == 0)
693  fGamma_vs_z = new TProfile();
694 
695  if (fdEdX_vs_z == 0)
696  fdEdX_vs_z = new TProfile();
697 
698  fStatTree->Fill();
699 
700  delete fLorenzo_vs_X;
701  delete fdNdX;
702  delete fCharged;
703  delete fMuon;
704  delete fElectron;
705  delete fGamma;
706  delete fdEdX;
707  delete fLorenzo;
708  delete fdNdz;
709  delete fCharged_vs_z;
710  delete fMuon_vs_z;
711  delete fElectron_vs_z;
712  delete fGamma_vs_z;
713  delete fdEdX_vs_z;
714 
715  }
716  // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
717 
718  // Lorenzos TimeModel
719  MuonTimeModel* lorenzoTimeModel = nullptr;
720  if (!fPlaneFront) {
721 
723 
724  if (hasMuonProductionProfile) {
725 
726  if (fVerbosity > 2)
727  INFO("TimeModel from MuonProduction Profile");
728  TabulatedFunction logZdist =
729  GetLogZdist(SimMuonProductionProfile, simCore, simAxis);
730 
731  lorenzoTimeModel = new MuonTimeModel(fRandomEngine, Zenith, &logZdist, true, true);
732 
733  } else if (hasMuonProfile) {
734 
735  WARNING ("TimeModel from Muon-Profile: NOT PROPERLY IMPLEMENTED YET");
736 
737  TabulatedFunction logZdist =
738  CalculateLogZdist(SimMuonProfile, absCosTheta, XobsVert);
739 
740  lorenzoTimeModel = new MuonTimeModel(fRandomEngine, Zenith, &logZdist, true, true);
741 
742  } else {
743 
744  ERROR("no muon profiles available, to init time model!");
745  return eFailure;
746 
747  }
748 
749  } else {
750  if (fVerbosity > 2)
751  INFO("TimeModel from parametrisation");
752  const double logE = log10(simEnergy/eV);
753  lorenzoTimeModel = new MuonTimeModel(fRandomEngine, Zenith, logE, lorenzoPrimary);
754  }
755 
756  if (fVerbosity > 2)
757  lorenzoTimeModel->Info();
758 
759  } // not plane shower front
760 
762  // calcualte S1000 ////////////////////
763 
764  const double XobsS1000 = XobsVert / absCosTheta;
765 
766  // if the profile range is exceeded, try fitting the range after maximum
767  // if fit fails (for muon-number-profile) use simple muon decay of last entry
768 
769  double Ne = 0;
770  double Ng = 0;
771  double Nmu = 0;
772 
773  if (XobsS1000 > ProfileMaxDepth) {
774  WARNING("Shower does not reach ground! Extrapolate profile!");
775 
776  if (fProfileExtrapolation[ShowerSimData::eMuon].p0 == 0 &&
777  fProfileExtrapolation[ShowerSimData::eMuon].p1 == 0) { //extrapolation failed
778  const double NmuLastPoint = SimMuonProfile[SimMuonProfile.GetNPoints()-1].Y();
779  const double depthLastPoint = SimMuonProfile[SimMuonProfile.GetNPoints()-1].X()/g*cm2;
780  const double distanceLastPoint = (log(depthLastPoint) - fSlantDepthExtrapolation.p0)/fSlantDepthExtrapolation.p1/m;
781  const double gammaFactor = 10;
782 
783  Nmu = NmuLastPoint * exp((distanceLastPoint/m - HeightObs/m) / (kSpeedOfLight/m*s * kMuonLifetime/s * gammaFactor));
784 
785  if (fVerbosity > 3) {
786  ostringstream dbg;
787  dbg <<" Nmu-profile (last point)= "<<NmuLastPoint
788  <<" Depth (last point)= "<<depthLastPoint
789  <<" distance (last point)= "<<distanceLastPoint
790  <<" height needed= "<<HeightObs
791  <<" gammaFactor= "<<gammaFactor
792  <<" --> Nmu= "<<Nmu;
793  INFO(dbg);
794  }
795  } else {
796  Nmu = exp(fProfileExtrapolation[ShowerSimData::eMuon].p0 +
797  fProfileExtrapolation[ShowerSimData::eMuon].p1 * XobsS1000/g*cm2);
798  }
799 
800  Ng = exp(fProfileExtrapolation[ShowerSimData::ePhoton].p0 +
801  fProfileExtrapolation [ShowerSimData::ePhoton].p1 * XobsS1000/g*cm2);
802  Ne = exp(fProfileExtrapolation[ShowerSimData::eElectron].p0 +
803  fProfileExtrapolation [ShowerSimData::eElectron].p1 * XobsS1000/g*cm2);
804  } else {
805  Nmu = SimMuonProfile.Y(XobsS1000);
806  Ng = SimGammaProfile.Y(XobsS1000);
807  Ne = SimElectronProfile.Y(XobsS1000);
808  }
809 
810  const double Age = utl::ShowerAge(XobsS1000, Xmax);
811  const double Rm = utl::MoliereRadius(Temperature, Pressure, absCosTheta);
812 
813  // ---------INFO-----------
814  if (fVerbosity > 3) {
815  ostringstream dbg;
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;
820  INFO(dbg);
821  }
822  // --------------------
823 
824  const double S1000 = CalculateTankSignal(1000.*m, 1.8*m, 1.2*m, Zenith,
825  Age, Rm,
826  Ne, Ng, Nmu, false);
827 
828  // ---------INFO-----------
829  if (fVerbosity > 3) {
830  ostringstream dbg;
831  dbg << " S1000 " << S1000 << " Energy/EeV " << simEnergy/EeV << endl;
832  dbg << " ********* calculated S1000 ********** ";
833  INFO(dbg);
834  }
835  // --------------------
836 
837  int closestStationID = -1;
838 
839  // ---------------------------------------------------------------------
840  // loop stations to find closest one
842 
843  double closestStationDistance = 0;
844 
845  for (sdet::SDetector::StationIterator iStation = SDet.StationsBegin();
846  iStation != SDet.StationsEnd(); ++iStation) {
847 
848  const int tankID = iStation->GetId();
849 
851  const Point& tankPos = iStation->GetPosition();
852 
853  const double PosXinShower = tankPos.GetX(ShowerCS);
854  const double PosYinShower = tankPos.GetY(ShowerCS);
855  //double PosZinShower = tankPos.GetZ(ShowerCS);
856 
857  const double coreDistance = sqrt(PosXinShower*PosXinShower +
858  PosYinShower*PosYinShower);
859 
860  if (closestStationID < 0 || coreDistance < closestStationDistance) {
861 
862  // skip stations not T2-alive
863  if (fUseT2LifeTime) {
864  if (iStation->IsInAcquisition()) {
865  closestStationID = tankID;
866  closestStationDistance = coreDistance;
867  }
868  } else {
869  closestStationID = tankID;
870  closestStationDistance = coreDistance;
871  }
872  }
873 
874  } // end loop stations
875  }
876 
877  int nNotInDAQ = 0;
878 
879  // ----------------------------------------------------------------------
880  // loop stations (detector definitions)
881  for (sdet::SDetector::StationIterator iStation = SDet.StationsBegin();
882  iStation != SDet.StationsEnd(); ++iStation) {
883 
884  // skip stations, and don't push it into the SEvent, if is was not T2-alive
885  if (fUseT2LifeTime && !iStation->IsInAcquisition()) {
886  ++nNotInDAQ;
887  continue;
888  }
889 
890  const int tankID = iStation->GetId();
891 
892  // ------------------------------------------------------------------
893  // Create station - event
894  // (ALL stations are part of the event !)
895  //
896  if (sEvent.HasStation(tankID)) {
897  ERROR("StationID occured twice in detector !!!!!! skipping !!!");
898  continue;
899  }
900  sEvent.MakeStation(tankID);
901  sevt::Station& tank = sEvent.GetStation(tankID);
902 
903  // don't forget the tank trigger data
904  // trigger is eNone and errorCode=1
905  tank.MakeTriggerData();
906  sevt::StationTriggerData& stationTrigger = tank.GetTriggerData();
907 
908 //#warning How to properly calculate FD-T3 time offsets for the stations? Need FD T3!
909 
911  int errorCode = 2;
912  int timeOffset = 0;
913  double timeWindow = GetCDASTriggerTimeWindow(coreTime);
914  stationTrigger.SetOffsetMicroSecond(timeOffset / microsecond);
915  stationTrigger.SetWindowMicroSecond(timeWindow / microsecond);
916  stationTrigger.SetAlgorithm(tankTriggerAlgo);
917  stationTrigger.SetErrorCode(errorCode);
918  //stationTrigger.SetPLDTrigger(const int trigger);
919 
920  // DV: setting stations to silent prevents later setting it to candidate;
921  // all stations should be kept candidate and at the end all stations
922  // wothout an signal should be set tank.SetSilent(); // all station are created 'silent'
923  // ----------------------------------------------------------------
924 
925  // check if only closest station should be simulated
926  if (fOnlyClosestTank && tankID != closestStationID)
927  continue;
928 
930  const Point& tankPos = iStation->GetPosition();
931 
932  const double PosXinShower = tankPos.GetX(ShowerCS);
933  const double PosYinShower = tankPos.GetY(ShowerCS);
934  const double PosZinShower = tankPos.GetZ(ShowerCS);
935 
936  const double coreDistance = sqrt(PosXinShower*PosXinShower + PosYinShower*PosYinShower);
937 
938  /*if (coreDistance > fLateralCut) {
939  continue;
940  }*/
941 
943  const Point tankAtAxis(0,0, PosZinShower, ShowerCS);
944 
945  const double tankOverSeaLevel =
946  wgs84.PointToLatitudeLongitudeHeight(tankPos).get<2>();
947 
948  const double tankAtAxisOverSeaLevel =
949  wgs84.PointToLatitudeLongitudeHeight(tankAtAxis).get<2>();
950 
951  const Vector tankAtAxisToCore = tankAtAxis - simCore;
952  const double distanceTankAtAxisToCore = tankAtAxisToCore.GetMag();
953  const double distanceFromCoreAtAxis = distanceTankAtAxisToCore *
954  (tankAtAxisToCore*simAxis < 0 ? 1 : -1);
955 
956  //double tankOverSeaLevel = UTMPoint(tankPos, wgs84).GetHeight();
957  //double ThetaOftankInShower = (showerStart - tankPos).GetTheta(siteCS);
958 
959  // ---------INFO-----------
960  if (fVerbosity > 3) {
961  ostringstream dbg;
962  dbg << " tank " << tankID
963  << " height@axis " << tankAtAxisOverSeaLevel
964  << " AtmMin " << atmDistanceMin
965  << " AtmMax " << atmDistanceMax;
966  INFO(dbg);
967  }
968  // --------------------
969 
970  bool flagAtmExceeded = false;
971  double xTank = 0;
972  if (distanceFromCoreAtAxis < atmDistanceMin ||
973  distanceFromCoreAtAxis > atmDistanceMax) {
974 
975  // ---------INFO-----------
976  if (fVerbosity > 3) {
977  ostringstream dbg;
978  dbg << " ATM EXCEEDED: "
979  << " TankR: " << coreDistance/m
980  << " TankAtAxisOverSeaLevel: " << tankAtAxisOverSeaLevel/m
981  << " DistanceAtAxisFromCore: " << distanceFromCoreAtAxis/m
982  << " min " << atmDistanceMin << " " << atmDistanceMax;
983  INFO(dbg);
984  }
985  // --------------------
986 
987  xTank = exp(fSlantDepthExtrapolation.p0 + fSlantDepthExtrapolation.p1 * distanceFromCoreAtAxis) * g/cm2;
988 
989  flagAtmExceeded = true;
990 
991  } else {
992 
993  //tankAtAxisOverSeaLevel);
994  xTank = slantDepthVsDistance.Y(distanceFromCoreAtAxis);
995 
996  }
997 
998  const double tankRadius = iStation->GetRadius();
999  const double tankHeight = iStation->GetHeight();
1000 
1001  if (coreDistance > fLateralCut) {
1002  //tank.SetSilent();
1003  continue;
1004  }
1005 
1007  double Xobs = xTank;
1008 
1009  bool ShowerProfileRangeExceeded = false;
1010  if (Xobs > ProfileMaxDepth) {
1011 
1012  ShowerProfileRangeExceeded = true;
1013  //Xobs = ProfileMaxDepth;
1014  }
1015 
1016  // ---------INFO-----------
1017  if (fVerbosity > 1) {
1018  ostringstream dbg;
1019  dbg << " ShowerProfileRangeExceeded " << ShowerProfileRangeExceeded
1020  << " maxX " << ProfileMaxDepth/g*cm*cm
1021  << " Xobs " << Xobs/g*cm*cm
1022  << " Xobs " << Xobs
1023  << " " << SimMuonProfile[0].X()
1024  << " " << SimMuonProfile[SimMuonProfile.GetNPoints()-1].X()
1025  << " " << SimMuonProfile[0].X()/g*cm2
1026  << " " << SimMuonProfile[SimMuonProfile.GetNPoints()-1].X()/g*cm2;
1027  INFO(dbg);
1028  }
1029  // --------------------
1030 
1031  // ---------INFO-----------
1032  if (fVerbosity > 1 && ShowerProfileRangeExceeded) {
1033  ostringstream dbg;
1034  dbg << " ele "
1035  << " p0 " << fProfileExtrapolation [ShowerSimData::eElectron].p0
1036  << " p1 " << fProfileExtrapolation [ShowerSimData::eElectron].p1
1037  << " gam "
1038  << " p0 " << fProfileExtrapolation [ShowerSimData::ePhoton].p0
1039  << " p1 " << fProfileExtrapolation [ShowerSimData::ePhoton].p1
1040  << " muo "
1041  << " p0 " << fProfileExtrapolation [ShowerSimData::eMuon].p0
1042  << " p1 " << fProfileExtrapolation [ShowerSimData::eMuon].p1;
1043  INFO(dbg);
1044  }
1045  // --------------------
1046 
1047  // if the profile range is exceeded, try fitting the range after maximum
1048  // if fit fails (for muon-number-profile) use simple muon decay of last entry
1049  double Ne = 0;
1050  double Ng = 0;
1051  double Nmu= 0;
1052  if (ShowerProfileRangeExceeded) {
1053  if (fProfileExtrapolation[ShowerSimData::eMuon].p0 == 0 &&
1054  fProfileExtrapolation[ShowerSimData::eMuon].p1 == 0) { //extrapolation failed
1055  const double NmuLastPoint = SimMuonProfile[SimMuonProfile.GetNPoints()-1].Y();
1056  const double depthLastPoint = SimMuonProfile[SimMuonProfile.GetNPoints()-1].X()/g*cm2;
1057  const double distanceLastPoint = (log(depthLastPoint) - fSlantDepthExtrapolation.p0)/fSlantDepthExtrapolation.p1/m;
1058  const double gammaFactor = 10;
1059 
1060  Nmu = NmuLastPoint *
1061  exp((distanceLastPoint/m - distanceFromCoreAtAxis/m)/(kSpeedOfLight/m*s * kMuonLifetime/s *gammaFactor));
1062 
1063  if (fVerbosity > 3) {
1064  ostringstream dbg;
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;
1071  INFO(dbg);
1072  }
1073  } else {
1074  Nmu = exp(fProfileExtrapolation[ShowerSimData::eMuon].p0 +
1075  fProfileExtrapolation[ShowerSimData::eMuon].p1 * Xobs/g*cm2);
1076  }
1077 
1078  Ng = exp(fProfileExtrapolation[ShowerSimData::ePhoton].p0 +
1079  fProfileExtrapolation[ShowerSimData::ePhoton].p1 * Xobs/g*cm2);
1080  Ne = exp(fProfileExtrapolation[ShowerSimData::eElectron].p0 +
1081  fProfileExtrapolation[ShowerSimData::eElectron].p1 * Xobs/g*cm2);
1082  } else {
1083  Nmu = SimMuonProfile.Y(Xobs);
1084  Ng = SimGammaProfile.Y(Xobs);
1085  Ne = SimElectronProfile.Y(Xobs);
1086  }
1087 
1088  const double Age = utl::ShowerAge(Xobs, Xmax);
1089  const double Rm = utl::MoliereRadius(Temperature, Pressure, absCosTheta);
1090  double tankSignal =
1091  CalculateTankSignal(coreDistance, tankRadius, tankHeight, Zenith, Age, Rm, Ne, Ng, Nmu);
1092 
1093  // ---------INFO-----------
1094  if (fVerbosity > 3) {
1095  ostringstream dbg;
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;
1101  INFO(dbg);
1102  }
1103  // --------------------
1104 
1105  //bool tankIsForced = false; // unused
1106 
1107  if (tankSignal < 0.01) {
1108  if (fVerbosity > 3) {
1109  ostringstream dbg;
1110  dbg << " tank " << tankID
1111  << " has signal < 0.01 (closestStation= " << closestStationID << ") ";
1112  INFO(dbg);
1113  }
1114 
1115  if (fForceClosestTankToTrigger && tankID == closestStationID) {
1116  if (fVerbosity > 1) {
1117  ostringstream infoString;
1118  infoString << "Forcing tank trigger for tank signal (previous) S=" << tankSignal << " set to S=5";
1119  // tankIsForced = true; // unused
1120  INFO(infoString);
1121  }
1122  // use a fixed tank signal for non-triggered tanks with
1123  // fForceClosestTankToTrigger
1124  tankSignal = 5;
1125  } else {
1126  if (fVerbosity > 3) {
1127  INFO(" setting to silent");
1128  }
1129  //tank.SetSilent(); <-- should not be done here
1130  continue;
1131  }
1132  }
1133 
1134  // Shower plane - simulated arrival time
1135 
1136  double tankPlaneSimTime = - PosZinShower / kSpeedOfLight;
1137 
1138  // Set simulation truth for all tanks: time, signal (components)
1139  if (tank.HasSimData()) {
1140  ostringstream msg;
1141  msg << "Station " << tank.GetId() << " already has SimData!";
1142  WARNING(msg);
1143  } else {
1144  tank.MakeSimData();
1145  }
1146  sevt::StationSimData& tankSim = tank.GetSimData();
1147  tankSim.SetSimulatorSignature("SdSimpleSimKG");
1148 
1149  TimeInterval tankSimTime = tankPlaneSimTime;
1150  /*
1151  Particle muons(Particle::eMuon, Particle::eShower, tankPos, simAxis, tankSimTime, fNMuons, fSMuons);
1152  Particle electrons(Particle::eElectron, Particle::eShower, tankPos, simAxis, tankSimTime, fNElectrons, fSElectrons);
1153  Particle gammas(Particle::ePhoton, Particle::eShower, tankPos, simAxis, tankSimTime, fNGammas, fSGammas);
1154  tankSim.AddParticle(muons);
1155  tankSim.AddParticle(electrons);
1156  tankSim.AddParticle(gammas);
1157  */
1158  tankSim.SetPlaneFrontTime(coreTime + tankSimTime);
1159 
1161 
1162  const double p_trig = T1TriggerProbability(tankSignal, S1000, Zenith/deg);
1163 
1164  // ----------INFO-----------
1165  if (fVerbosity > 3) {
1166  ostringstream dbg;
1167  dbg << " p_trig " << p_trig;
1168  INFO(dbg);
1169  }
1170  // ---------------------
1171 
1172  if (fForceClosestTankToTrigger && tankID == closestStationID) {
1173  ; // do nothing
1174  } else {
1175  if (RandFlat::shoot(&fRandomEngine.GetEngine(), 0.0, 1.0) > p_trig) {
1176 
1177  if (fVerbosity > 0) {
1178  ostringstream info;
1179  info << "tank id="<< tankID
1180  << " r=" << coreDistance/m << "m"
1181  " S=" << tankSignal << "VEM"
1182  " p_trig=" << p_trig
1183  << " (NO TRIGGER)";
1184  INFO(info);
1185  }
1186 
1187  //tank.SetSilent(); <-- should not be done here
1188  continue;
1189  }
1190  }
1191 
1192  //if (tankSignal>10)
1193  //tankTriggerAlgo = sevt::StationTriggerData::eThreshold;
1194 
1195  //if (ShowerProfileRangeExceeded || flagAtmExceeded) {
1196  if (flagAtmExceeded && fVerbosity > 2) {
1197 
1198  // if we really enter here, there is a station with a possible signal, that
1199  // can not get calculated from the given shower profile.
1200 
1201  ostringstream warn;
1202  warn << "Shower profile range exceeded "
1203  "(" << (ShowerProfileRangeExceeded ? "true" : "false")
1204  << ")! "
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
1210  << "g/cm2 !!!\n"
1211  << "(Signal: " << tankSignal << ", "
1212  "p_trig: " << p_trig << ", "
1213  "nMuon: " << fNMuons << ", "
1214  "nElectrons: " << fNElectrons << ", "
1215  "nGammas: " << fNGammas << ")";
1216  WARNING(warn);
1217 
1218  //return eContinueLoop;
1219  }
1220 
1222  // Shower plane - approximation
1223 
1224  double tankTime = tankSimTime.GetInterval();
1225 
1226  /*
1227  from Lorenzo Cazon
1228  */
1229  const double R = tankPos.GetRho(ShowerCS);
1230  double Phi = tankPos.GetPhi(ShowerCS);
1231  if (!fPlaneFront) {
1232 
1233  while (Phi < 0)
1234  Phi += 360.*deg;
1235  lorenzoTimeModel->SetCoordinates(R/m, Phi/rad);
1236 
1237  //if (!tankIsForced) { // what is this good for ????
1238  if (fNMuons) {
1239 //#warning Need confirmation from Lorenzo !!
1240 
1241  // limit number of muons
1242  int nDice = fNMuons;
1243  if (nDice > 1000)
1244  nDice = 1000;
1245  tankTime = lorenzoTimeModel->GetFirstTime(fNMuons);
1246 
1247  } else {
1248 
1249 //#warning Need electron arrival time model here !!
1250  WARNING(" TIME-MODEL: Muon-model timing for signal without muons !!! Use nMuon=1");
1251  //continue;
1252  tankTime = lorenzoTimeModel->GetFirstTime(1.0);
1253 
1254  }
1255  //}
1256  }
1257 
1258  // Detector time-resolution
1259  // dependent on FADC trace (shower width, particle distribution,
1260  // FADC traces)
1261  // from GAP 2005-035
1262  static const double constK = 5.368e-5*ns/(m*m);
1263 
1264  static const double SigmaT0 = 26.84*ns;
1265 
1266  double sigmaTime = 0;
1267  if (!fPlaneFront) // shower to shower fluctuations already from Lorenzo
1268  sigmaTime = SigmaT0; // --> only detector resolution needs to be added
1269  else
1270  sigmaTime = sqrt(SigmaT0*SigmaT0 + pow(constK*R*R*absCosTheta, 2));
1271 
1272  double deltaT = RandGauss::shoot(&fRandomEngine.GetEngine(), 0, sigmaTime);
1273 
1274  tankTime += deltaT;
1275  // --- end of calculation of arrival times -----------
1276 
1278  utl::TimeStamp stationTime = coreTime + TimeInterval(tankTime);
1279 
1280  if (First) {
1281  First = false;
1282  TriggerTime = stationTime;
1283  } else {
1284  if (TriggerTime > stationTime)
1285  TriggerTime = stationTime;
1286  }
1287 
1289  errorCode = 0;
1290  stationTrigger.SetAlgorithm(tankTriggerAlgo);
1291  stationTrigger.SetErrorCode(errorCode);
1292 
1293  /*if (tankSignal < 1) { closestStationID
1294  tank.SetSilent(); // this is not done here, but in SdEventSelector
1295  continue;
1296  }*/
1297 
1298  // What about saturated stations?
1299  tank.SetHighGainSaturation(false);
1300  tank.SetLowGainSaturation(false);
1301  tank.SetCandidate();
1302 
1303  // If not silent, fill the rec-data
1304  tank.MakeRecData();
1305  sevt::StationRecData& tankRec = tank.GetRecData();
1306 
1307  tankRec.SetTotalSignal(tankSignal);
1308  tankRec.SetSignalStartTime(stationTime);
1309 
1310  if (fVerbosity > 0) {
1311  ostringstream info;
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]";
1319  if (fVerbosity > 3)
1320  info << " z_sh=" << PosZinShower/m << "m"
1321  << " z_sh/c= " << PosZinShower/kSpeedOfLight << "ns";
1322  INFO(info.str());
1323 
1324  // cout << endl;
1325  }
1326 
1327  } // loop stations
1328 
1329  delete lorenzoTimeModel;
1330 
1331  if (nNotInDAQ) {
1332  ostringstream info;
1333  info << "There have been " << nNotInDAQ << " stations not in DAQ accoring to T2 life file!";
1334  INFO(info);
1335  }
1336 
1337  if (!sEvent.HasTrigger())
1338  sEvent.MakeTrigger();
1339 
1340  sevt::EventTrigger& STrigger = sEvent.GetTrigger();
1341  STrigger.SetTime(TriggerTime);
1342  STrigger.SetAlgorithm("FD");
1343  //STrigger.SetSender("FD");
1344  //STrigger.SetId("FD");
1345  //STrigger.SetPreviousId("FD");
1346  //STrigger.SetNumberOfStations("FD");
1347  //STrigger.SetSDPAngle();
1348 
1349  // THE NOISE loop
1350  // loop all stations again
1351  if (fNoise) {
1352 
1353  // ---------INFO--------------
1354  if (fVerbosity > 3)
1355  INFO(" -------->noise ");
1356  // -----------------------
1357 
1358  int nNoiseTank = 0;
1359  int nSignalNoiseTank = 0;
1360 
1361  // -------------------------------------------------------------------------
1362  // noise loop
1363  for (sdet::SDetector::StationIterator iStation = SDet.StationsBegin();
1364  iStation != SDet.StationsEnd(); ++iStation) {
1365 
1366  // skip stations, which are not T2-alive
1367  if (fUseT2LifeTime) {
1368  if (!iStation->IsInAcquisition()) {
1369  continue;
1370  }
1371  }
1372 
1373  int tankID = iStation->GetId();
1374 
1375  // central trigger (station) time window
1376  double timeWindow = GetCDASTriggerTimeWindow(coreTime);
1377  double timeOffset = 0;
1378 
1379  // station is not part of event yet (-> cannot happen ... )
1380  // if station had no shower signal yet
1381  if (!sEvent.HasStation (tankID)) {
1382 
1383  if (Noise(sEvent, TriggerTime, tankID, timeOffset, timeWindow))
1384  ++nNoiseTank;
1385 
1386  continue;
1387  }
1388 
1389  sevt::Station& tank = sEvent.GetStation(tankID);
1390 
1391  // check for TRIGGER and adjust TimeWindow, TimeOffset
1392  if (true == false && // turn off noise for signal stations
1393  tank.HasTriggerData() &&
1397 
1398  const double fadcTraceLength = iStation->GetFADCTraceLength() * iStation->GetFADCBinSize();
1399  timeWindow = fadcTraceLength;
1400  timeOffset = 0;
1401  if (Noise(sEvent, TriggerTime, tankID, timeOffset, timeWindow)) {
1402  ++nNoiseTank;
1403  ++nSignalNoiseTank;
1404  }
1405 
1406  continue;
1407  }
1408 
1409  // tank belong to event, but had no trigger yet
1410  if (Noise(sEvent, TriggerTime, tankID, timeOffset, timeWindow))
1411  ++nNoiseTank;
1412 
1413  } // end noise loop
1414 
1415  if (fVerbosity > 1) {
1416  ostringstream inf;
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.";
1421  }
1422  INFO(inf);
1423  }
1424 
1425  } // end noise loop ----------------------------------------------------------
1426 
1427  // ---------INFO--------------
1428  if (fVerbosity > 3)
1429  INFO( "noise ");
1430  // -----------------------
1431 
1432  // all the stations without the signal should be switched from candidate --> silent
1433  for (auto& station : boost::make_iterator_range(sEvent.StationsBegin(), sEvent.StationsEnd())) {
1434  if (!station.HasRecData() || !station.GetRecData().GetTotalSignal())
1435  station.SetSilent();
1436  }
1437 
1438  return eSuccess;
1439 }
1440 
1441 
1444 {
1445  if (fStatTree) {
1446  TFile* const file = fStatTree->GetCurrentFile();
1447  file->cd();
1448  fStatTree->Write();
1449  file->Close();
1450  delete file;
1451  }
1452 
1453  return eSuccess;
1454 }
1455 
1456 
1457 // ldf function from ldffinderOG
1458 /*inline
1459 double
1460 SdSimpleSim::LDFFunction(const double r, const double beta, const double gamma)
1461 {
1462  if (LDFFinder::fgLDFType == LDFFinder::ePL) {
1463  const double nearCore = kNearRadius / k1000m;
1464  const double relR = r / k1000m;
1465  return pow(relR, beta + gamma*log(relR > nearCore ? relR : nearCore));
1466  } else
1467  return pow(r/k1000m, beta)*pow((700*meter + r)/(1700*meter), beta+gamma);
1468 }*/
1469 
1470 
1471 double
1472 SdSimpleSim::NKG(double N, double Rmoliere, double R, double s)
1473 {
1474  if (s >= 2.25) {//Gamma(x) is only defined for x>0
1475  if (fVerbosity > 1) {
1476  ostringstream inf;
1477  inf <<"trying to use the NKG function outside valid range (age<=2.25): age= "<<s<<" --> using constant age = 2.24";
1478  WARNING(inf);
1479  }
1480  s = 2.24;
1481  }
1482  // normalize to Rmoliere
1483  R /= Rmoliere;
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);
1486  return rho;
1487 }
1488 
1489 
1490 bool
1492  const utl::TimeStamp& T0,
1493  int tankID,
1494  double timeOffset, double timeWindow)
1495 {
1496  if (!IsNoise(timeWindow))
1497  return false;
1498 
1499  if (fVerbosity > 2)
1500  INFO(" ++++++++++++++++++++== generate noise!! +++++++++++++++");
1501 
1503  if (!sEvent.HasStation(tankID))
1504  sEvent.MakeStation(tankID);
1505 
1506  sevt::Station& tank = sEvent.GetStation(tankID);
1507 
1508  if (!tank.HasSimData())
1509  tank.MakeSimData();
1510  sevt::StationSimData& tankSim = tank.GetSimData();
1511  tankSim.SetSimulatorSignature("SdSimpleSimKG");
1512 
1513  /*
1514  // get reference coordinate system of detector (usually PampaAmarilla)
1515  const utl::CoordinateSystemPtr referenceCS = det::Detector::GetInstance().GetReferenceCoordinateSystem();
1516  Point pos(0,0,0,referenceCS);
1517  Vector dir(0,0,0,referenceCS);
1518  Particle fake((int)Particle::eMuon, Particle::eBackground,
1519  pos, dir, TimeInterval(0), 0., 0.);
1520  tankSim.AddParticle(fake);
1521  */
1522  if (!tank.HasRecData())
1523  tank.MakeRecData();
1524 
1525  //sevt::StationRecData& tankRec = tank.GetRecData();
1526  double Signal = GenerateNoiseStation(tank, T0, timeOffset, timeWindow);
1527 
1528  // noise trigger type according to TOT rate (see astro-ph/0510320)
1529 
1530  const double timeOverThresholdRate = 1.6*hertz;
1531 
1532  double r = RandFlat::shoot(&fRandomEngine.GetEngine(), 0.0, 1.0);
1533 
1534  sevt::StationTriggerData::Algorithm tankTriggerAlgo;
1535  if (r > timeOverThresholdRate/fNoiseRatePerStation)
1536  tankTriggerAlgo = sevt::StationTriggerData::eT1Threshold;
1537  else
1539 
1540  // don't forget the tank trigger data
1541  if (!tank.HasTriggerData())
1542  tank.MakeTriggerData();
1543 
1544  sevt::StationTriggerData& stationTrigger = tank.GetTriggerData();
1545 
1546  //#warning How to properly calculate FD-T3 time offsets for the NOISE-stations?
1547 
1548  //int TimeOffset = 0;
1549  //double TimeWindow = GetCDASTriggerTimeWindow()
1550  stationTrigger.SetOffsetMicroSecond(timeOffset / microsecond);
1551  stationTrigger.SetWindowMicroSecond(timeWindow / microsecond);
1552  //stationTrigger.SetErrorCode(const int errorCode);
1553  //stationTrigger.SetPLDTrigger(const int trigger);
1554  stationTrigger.SetAlgorithm(tankTriggerAlgo);
1555 
1556  if (fVerbosity > 2) {
1557  ostringstream dbg;
1558  dbg << " noise stations: " << tankID << " signal: " << Signal << "VEM "
1559  << " trigger: " << (tankTriggerAlgo == sevt::StationTriggerData::eT1Threshold ? "threshold" : "TOT");
1560  INFO(dbg);
1561  }
1562 
1563  return true;
1564 }
1565 
1566 
1567 bool
1568 SdSimpleSim::IsNoise(double TimeWindow)
1569 {
1570  double NoiseEvents = 2.*TimeWindow*fNoiseRatePerStation;
1571  double r = RandFlat::shoot(&fRandomEngine.GetEngine(), 0.0, 1.0);
1572 
1573  // we support only up to one noise hit per TimeWindow .....
1574 
1575  if (r < NoiseEvents) {
1576  return true;
1577  }
1578 
1579  return false;
1580 }
1581 
1582 
1583 /*
1584  parameterized signal distribution for noise tanks, as seen from brass hybrid
1585  SD files (without shower stations)
1586 */
1587 double
1589  const utl::TimeStamp& T0,
1590  double TimeOffset,
1591  double TimeWindow)
1592 {
1593  sevt::StationRecData& noiseStation = tank.GetRecData();
1594 
1595  double Time = RandFlat::shoot(&fRandomEngine.GetEngine(),
1596  -TimeWindow, TimeWindow);
1597 
1598  utl::TimeStamp stationTime = T0 + utl::TimeInterval(TimeOffset+Time);
1599 
1600  //cout << " trig: " << T0 << endl;
1601  //cout << " " << Time << " " << TimeOffset << " " << TimeWindow << endl;
1602  //cout << "new: " << stationTime << endl;
1603 
1604  // parameters from analysis of data file: sd_2004_10_16_01h51.root
1605  // joining at mean+2*sigma !!!! = .6039
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;
1616 
1617  double log10VEM;
1618  double r0 = RandFlat::shoot(&fRandomEngine.GetEngine(), 0., 1.);
1619  //cout << " p_gaus: " << p_gaus << " " << r0 << endl;
1620  if (r0 < p_gaus) {
1621 
1622  // sample from gaus!
1623  //cout << "gauss ";
1624  do {
1625  log10VEM = RandGauss::shoot(&fRandomEngine.GetEngine(),
1626  Mean, Sigma);
1627  } while (log10VEM > JoiningPoint);
1628 
1629  } else {
1630 
1631  //cout << "expo ";
1632  // sample from expo!
1633  double r = RandFlat::shoot(&fRandomEngine.GetEngine(), 0., 1.);
1634  double N = 1./(Slope) * exp(-Slope*JoiningPoint);
1635  log10VEM = log(r*N*(-Slope) + exp(-Slope*JoiningPoint)) / (-Slope);
1636  }
1637 
1638  double Signal = pow(10., log10VEM);
1639  double OldSignal = noiseStation.GetTotalSignal();
1640  Signal += OldSignal;
1641  noiseStation.SetTotalSignal(Signal);
1642 
1643  const utl::TimeStamp& OldTime = noiseStation.GetSignalStartTime();
1644 
1645  if (OldTime>stationTime ||
1646  OldSignal == 0) {
1647  noiseStation.SetSignalStartTime(stationTime);
1648  }
1649 
1650  tank.SetHighGainSaturation(false);
1651  tank.SetLowGainSaturation(false);
1652  tank.SetCandidate();
1653 
1654  return Signal;
1655 }
1656 
1657 
1658 double
1660  double phi,
1661  double z,
1662  double theta,
1663  double tankRadius)
1664 {
1665  double cosTheta = cos(theta);
1666  double sinTheta = sin(theta);
1667 
1668  double UntilBottom = 0;
1669  if (cosTheta != 0)
1670  UntilBottom = z / cos(theta);
1671 
1672  if (sinTheta == 0)
1673  return UntilBottom;
1674 
1675  double UntilSide = 0;
1676  if (sinTheta != 0)
1677  UntilSide = (tankRadius + r * cos(phi) -
1678  (tankRadius -
1679  sqrt(tankRadius*tankRadius -
1680  r * r * sin(phi) * sin(phi) ))) / sin(theta);
1681 
1682  if (cosTheta == 0)
1683  return UntilSide;
1684 
1685  return min(UntilSide, UntilBottom);
1686 }
1687 
1688 
1689 double
1690 SdSimpleSim::LTP(const double r,
1691  const double /*theta*/,
1692  const double /*energy*/)
1693 {
1694  const double Rltp = 1;
1695  const double Wltp = 1;
1696  return 1 / (1 + exp((r - Rltp) / Wltp));
1697 }
1698 
1699 
1700 /*
1701  Electron energy distribution as parameterized by F. Nerling
1702  */
1703 double
1704 SdSimpleSim::SampleEnergy(double Emin, double Emax, double Age)
1705 {
1706  Emin /= MeV;
1707  Emax /= MeV;
1708 
1709  //double a0 = 1.0;
1710  const double a1 = 6.42522 - 1.53183 * Age;
1711  const double a2 = 168.168 - 42.1368 * Age;
1712 
1713  double F2max = NerlingF2(Emin, a2, Age);
1714 
1715  double E;
1716  double accept;
1717  double r1, r2;
1718 
1719  // ---------INFO--------------
1720  int N = 0;
1721  // ----------------------
1722 
1723  do {
1724 
1725  // draw random number from Nerling F1
1726  r1 = RandFlat::shoot(&fRandomEngine.GetEngine(), 0., 1.);
1727  r2 = RandFlat::shoot(&fRandomEngine.GetEngine(), 0., 1.);
1728 
1729  E = exp(r1 * log (Emax+a1) + (1-r1) * log(Emin+a1)) - a1;
1730 
1731  // check with Nerling F2
1732  accept = NerlingF2(E, a2, Age);
1733 
1734  // ---------INFO--------------
1735  ++N;
1736  // ----------------------
1737 
1738  } while (accept/F2max < r2);
1739 
1740  E *= MeV;
1741 
1742  // ---------INFO--------------
1743  if (fVerbosity > 10) {
1744  ostringstream dbg;
1745  dbg << " sample-E: "
1746  << " Emin " << Emin
1747  << " Emax " << Emax
1748  << " age " << Age
1749  << E/MeV << " " << Age << " " << N;
1750  INFO(dbg);
1751  }
1752  // -----------------------
1753 
1754  return E;
1755 }
1756 
1757 
1758 /*
1759  The nerling dN/dE = F1*F2
1760 */
1761 double
1762 SdSimpleSim::NerlingF1(double E, double a1)
1763 {
1764  return 1. / (E + a1);
1765 }
1766 
1767 
1768 double
1769 SdSimpleSim::NerlingF2(const double E,
1770  const double a2,
1771  const double s)
1772 {
1773  return 1 / pow((E + a2), s);
1774 }
1775 
1776 
1779  const Point& /*core*/,
1780  const Vector& /*axis*/)
1781 {
1782  // convert X (slant depth) to z / m
1783  // taking care of earth curvature
1784  det::Detector& Det = det::Detector::GetInstance();
1785 
1786  const atm::ProfileResult heightProfile =
1788 
1789  const atm::ProfileResult depthProfile =
1791 
1792  const ProfileResult& distanceVsSlantDepth =
1794 
1795  double atmDepthMin = distanceVsSlantDepth.MinX();
1796  double atmDepthMax = distanceVsSlantDepth.MaxX();
1797 
1798  vector <double> ValueZ;
1799  vector <double> ValuedNdZ;
1800 
1801  // one bin in depth:
1802  double dXslant = abs(prof[1].X() - prof[0].X());
1803 
1804  for (unsigned int iBin = 0; iBin < prof.GetNPoints(); ++iBin) {
1805 
1806  double nDmu = prof [iBin].Y();
1807  double xSlant = prof [iBin].X();
1808 
1809  double xSlantLow = xSlant-dXslant/2;
1810  double xSlantHigh = xSlant+dXslant/2;
1811 
1812  //cout << " slant " << xSlant/g*cm*cm;
1813 
1814  if (xSlantLow < atmDepthMin || xSlantHigh > atmDepthMax) {
1815  /*
1816  cout << " continue "
1817  << " " << dXslant/g*cm*cm
1818  << " atmMin " << atmDepthMin/g*cm*cm
1819  << " atmMax " << atmDepthMax/g*cm*cm
1820  << endl;
1821  */
1822  continue;
1823  }
1824 
1825  const double distanceLow = distanceVsSlantDepth.Y(xSlantHigh);
1826  const double distanceHigh = distanceVsSlantDepth.Y(xSlantLow);
1827  const double distance = distanceVsSlantDepth.Y(xSlant);
1828 
1829  const double z = -distance;
1830  const double zLow = -distanceLow;
1831  const double zHigh = -distanceHigh;
1832 
1833  //cout << " profile: height " << height << " ndmu " << nDmu << flush;
1834 
1835  double dz = abs(zHigh - zLow);
1836 
1837  //cout << " dz " << dz << flush;
1838 
1839  // dont't go below ground leel
1840  if (z < 0) {
1841  //cout << endl;
1842  continue;
1843  }
1844 
1845  // only look at shower not before
1846  if (nDmu == 0) {
1847  //cout << endl;
1848  continue;
1849  }
1850 
1852  // normalisation is not required !!! ????
1853  double logz = log10(z);
1854  double dLogz = log10(dz);
1855  double dMuLogz = (nDmu*dXslant/dLogz) / g*cm*cm * m;
1856 
1857  //cout << " -> log10(z) " << logz << " " << dMuLogz << endl;
1858 
1859  ValueZ.insert(ValueZ.begin(), logz);
1860  ValuedNdZ.insert(ValuedNdZ.begin(), dMuLogz);
1861 
1862  }
1863 
1864  /*
1865  for (int i=0; i< ValueZ.size(); i++ ) {
1866 
1867  cout << ValueZ [i] << " " << ValuedNdZ [i] << endl;
1868  }
1869  */
1870 
1871  /*
1872  TabulatedFunction result(ValueZ, ValuedNdZ);
1873 
1874  cout << " ---------- result -------- " << endl;
1875  for (int i=0; i<result.GetNPoints(); i++) {
1876 
1877  cout << " ->> " << result[i].X() << " " << result[i].Y() << endl;
1878  }
1879  cout << " ---------- result -------- " << endl;
1880  return result;
1881  */
1882 
1883  return TabulatedFunction(ValueZ, ValuedNdZ);
1884 }
1885 
1886 
1889  const double cosTheta, const double xobs)
1890 {
1891  // convert X (slant depth) to z / m
1892  // taking care of earth curvature
1893  det::Detector& detector = det::Detector::GetInstance();
1894 
1895  const atm::ProfileResult heightProfile =
1896  detector.GetAtmosphere().EvaluateHeightVsDepth();
1897  const atm::ProfileResult depthProfile =
1898  detector.GetAtmosphere().EvaluateDepthVsHeight();
1899 
1900  const double heightXobs = heightProfile.Y(xobs);
1901 
1902  vector<double> valueZ;
1903  vector<double> valuedNdZ;
1904 
1905  const double atmDepthMin = depthProfile.Y(depthProfile.MaxX());
1906  const double atmDepthMax = depthProfile.Y(depthProfile.MinX());
1907 
1908  bool first = true;
1909  double z_old = 0;
1910  // double heightX_old = 0; // unused
1911  double nmu_old = 0;
1912  for (unsigned int iBin = 0; iBin < muonProfile.GetNPoints(); ++iBin) {
1913 
1914  const double nmu = muonProfile[iBin].Y();
1915  const double xslant = muonProfile[iBin].X();
1916  const double xvert = xslant * cosTheta;
1917 
1918  if (xvert < atmDepthMin || xvert > atmDepthMax)
1919  continue;
1920 
1921  const double heightX = heightProfile.Y(xvert);
1922  const double z = (heightX - heightXobs) / cosTheta;
1923 
1924  // only look at shower not before
1925  if (!nmu)
1926  continue;
1927 
1928  // first bin is for init only
1929  if (first) {
1930 
1931  first = false;
1932 
1933  z_old = z;
1934  // heightX_old = heightX; // unused
1935  nmu_old = nmu;
1936  continue;
1937  }
1938 
1939  const double dz = z - z_old;
1940  const double dN = nmu_old - nmu;
1941  const double zMean = 0.5*(z_old + z);
1942 
1943  // only look above the ground
1944  if (zMean <= 0)
1945  continue;
1946 
1947  valueZ.insert(valueZ.begin(), zMean);
1948  valuedNdZ.insert(valuedNdZ.begin(), dN/dz);
1949 
1950  z_old = z;
1951  // heightX_old = heightX; // unused
1952  nmu_old = nmu;
1953  }
1954 
1955  return TabulatedFunction(valueZ, valuedNdZ);
1956 }
1957 
1958 
1960 SdSimpleSim::FitDecay(const TabulatedFunction& profile, bool dEdX)
1961 {
1962  int nPoints = profile.GetNPoints();
1963 
1964  if (dEdX)
1965  --nPoints;
1966 
1967  // search for Xmax
1968  // start from "back" to find "last" maximum for camel-back events
1969  int maximumBin = 0;
1970  double maximum = 0;
1971  bool first = true;
1972 
1973  // use boxcar, to smooth fluctuations
1974  const int nBoxCar = 5;
1975  for (int i = 0; i < nPoints-nBoxCar; ++i) {
1976 
1977  // use boxcar, to smooth fluctuations
1978  double value = 0;
1979  //double depth = 0;// unused. LN.
1980  for (int iBoxCar = 0; iBoxCar < nBoxCar; ++iBoxCar) {
1981 
1982  int bin = nPoints - 1 - i - iBoxCar;
1983  value += profile[bin].Y();
1984  //depth += profile[bin].X();// unused. LN.
1985  }
1986  value /= nBoxCar;
1987  //depth /= nBoxCar;// unused. LN.
1988 
1989  if (first) {
1990  first = false;
1991  maximum = value;
1992  maximumBin = nPoints - 1 - i;
1993  } else {
1994  if (maximum < value) {
1995  maximum = value;
1996  maximumBin = nPoints - 1 - i;
1997  }
1998  }
1999  }
2000 
2001  // define intervall to be fit:
2002  // don't start at Xmax, because the exponential decay start later
2003  int startFitBin = maximumBin + int((nPoints - maximumBin) * 0.75);
2004 
2005  // ---------INFO--------------
2006  if (fVerbosity > 1) {
2007  ostringstream dbg;
2008  dbg << " profile fitting maxBin " << maximumBin
2009  << " startFitBin " << startFitBin
2010  << " nbins "<<nPoints;
2011  INFO(dbg);
2012  }
2013  // -----------------------
2014 
2015  if (nPoints - startFitBin < 3) {
2016  if (fVerbosity > 3) {
2017  ostringstream dbg;
2018  dbg << " failed profile extrapolation!\n"
2019  " tried to fit from bin " << startFitBin << " to " << nPoints;
2020  INFO(dbg);
2021  }
2022 
2023  return FitParam(0, 0);
2024  }
2025 
2026  // prepare linear-fit
2027  double S1 = 0;
2028  double Sx = 0;
2029  double Sxx = 0;
2030  double Sy = 0;
2031  double Sxy = 0;
2032  //double Syy = 0;// unused. LN.
2033  for (int i = startFitBin; i < nPoints; ++i) {
2034 
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);
2038 
2039  S1 += wi;
2040  Sx += wi * depth;
2041  Sxx += wi * depth * depth;
2042  Sy += wi * value;
2043  Sxy += wi * depth * value;
2044  //Syy += wi * value * value;// unused. LN.
2045  }
2046 
2047  const double det = S1*Sxx - Sx*Sx;
2048 
2049  const double a1 = (Sxx*Sy - Sx*Sxy) / det;
2050  const double a2 = (-Sx*Sy + S1*Sxy) / det;
2051 
2052  return FitParam (a1, a2);
2053 }
2054 
2055 
2058 {
2059  // fit 10 points of the last 20th of the profile
2060  const double minX = profile.MinX();
2061  const double maxX = profile.MaxX()-50*cm; // security boundary
2062 
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;
2067 
2068  // prepare linear-fit
2069  double S1 = 0;
2070  double Sx = 0;
2071  double Sxx = 0;
2072  double Sy = 0;
2073  double Sxy = 0;
2074  //double Syy = 0;// unused. LN.
2075  for (int i = 0; i < nPoints; ++i) {
2076 
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);
2080 
2081  S1 += wi;
2082  Sx += wi * x;
2083  Sxx += wi * x * x;
2084  Sy += wi * value;
2085  Sxy += wi * x * value;
2086  //Syy += wi * value * value;// unused. LN.
2087 
2088  }
2089 
2090  double D = S1*Sxx - Sx*Sx;
2091 
2092  double a1 = (Sxx*Sy - Sx * Sxy)/D;
2093  double a2 = (-Sx*Sy + S1*Sxy)/D;
2094 
2095  return FitParam (a1, a2);
2096 }
2097 
2098 
2099 double
2101  double tankRadius, double tankHeight, double Zenith,
2102  double Age, double Rm,
2103  double Ne, double Ng, double Nmu,
2104  bool fluctuation)
2105 {
2106  double cosTheta = cos (Zenith);
2107  double sinTheta = sin (Zenith);
2108 
2109  double tankProjTop = kPi * tankRadius * tankRadius * cosTheta;
2110  double tankProjSide = tankHeight * 2.* tankRadius * sinTheta;
2111  double tankProjArea = tankProjTop + tankProjSide;
2112 
2114 
2115  double RhoElectrons = NKG(Ne, Rm, coreDistance, Age/fEMAgeFactor);
2116  double RhoGammas = NKG(Ng, Rm, coreDistance, Age/fEMAgeFactor);
2117  double RhoMuons = NKG(Nmu, fMuonRScale, coreDistance, Age);
2118 
2119  double nElectrons = RhoElectrons * tankProjArea;
2120  double nGammas = RhoGammas * tankProjArea;
2121  double nMuons = RhoMuons * tankProjArea;
2122 
2123  if (fVerbosity > 5) {
2124  ostringstream dbg;
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;
2131  INFO(dbg);
2132  }
2133 
2134  if (fluctuation) {
2135  nElectrons = int(RandPoisson::shoot(&fRandomEngine.GetEngine(), nElectrons));
2136  nGammas = int(RandPoisson::shoot(&fRandomEngine.GetEngine(), nGammas));
2137  nMuons = int(RandPoisson::shoot(&fRandomEngine.GetEngine(), nMuons));
2138  }
2139 
2140  fNMuons = (int)nMuons;
2141  fNGammas = (int)nGammas;
2142  fNElectrons = (int)nElectrons;
2143 
2144  if (fVerbosity > 5) {
2145  ostringstream dbg;
2146  dbg << " nPart " << nElectrons << " " << nGammas << " " << nMuons << endl;
2147  INFO(dbg);
2148  }
2149 
2150  double nParticles = nElectrons + nGammas + nMuons;
2151 
2152  if (nParticles <= 1) { // no particles hit the tank
2153  return 0;
2154  }
2155 
2157  fSMuons = 0;
2158  int nSample = (fluctuation ? std::min(fNSample, int(nMuons)) : fNSample*10);
2159  if (nSample) {
2160  double Weight = nMuons / double(nSample);
2161  for (int iSample = 0; iSample < nSample; ++iSample) {
2162 
2163  const double p = RandFlat::shoot(&fRandomEngine.GetEngine(), 0, 1);
2164 
2165  double r;
2166  double phi;
2167  double z;
2168  if (p < tankProjTop/tankProjArea) { // hit tank-top
2169 
2170  // sample on top
2171  r = sqrt(RandFlat::shoot(&fRandomEngine.GetEngine(), 0, tankRadius*tankRadius));
2172 
2173  phi = RandFlat::shoot(&fRandomEngine.GetEngine(), 0, 2*kPi);
2174 
2175  z = tankHeight;
2176 
2177  } else { // hit tank-side
2178 
2179  // sample on side
2180  r = tankRadius;
2181 
2182  phi = asin(RandFlat::shoot(&fRandomEngine.GetEngine(), -1, 1));
2183 
2184  z = RandFlat::shoot(&fRandomEngine.GetEngine(), 0, tankHeight);
2185 
2186  }
2187 
2188  const double TrackLength = TankIntersection(r, phi, z, Zenith, tankRadius);
2189 
2190  if (fVerbosity > 10) {
2191  ostringstream dbg;
2192  dbg << " muon track/m: " << TrackLength/m;
2193  INFO(dbg);
2194  }
2195 
2196  fSMuons += Weight * TrackLength / kMeterPerVEM;
2197  }
2198  } // if nMuon>0
2199 
2201  fSElectrons = 0;
2202  nSample = (fluctuation ? std::min(fNSample, int(nElectrons)) : fNSample*10);
2203  if (nSample) {
2204  double Weight = nElectrons/(double)nSample;
2205  for (int iSample = 0; iSample < nSample; ++iSample) {
2206 
2207  //double Eem = MeanEnergy;
2208  static double Emin = 1e-2 * MeV;
2209  static double Emax = 1e+5 * MeV;
2210  double Eem = SampleEnergy(Emin, Emax, Age);
2211 
2212  fSElectrons += Weight * Eem * kTrackPerGEV / kMeterPerVEM;
2213  }
2214  } // if nElectrons>0
2215 
2217  fSGammas = 0;
2218  nSample = (fluctuation ? std::min(fNSample, int(nGammas)) : fNSample*10);
2219  if (nSample) {
2220  double Weight = nGammas/(double)nSample;
2221  for (int iSample = 0; iSample < nSample; ++iSample) {
2222 
2223  //double Eem = MeanEnergy;
2224  static double Emin = 1e-2 * MeV;
2225  static double Emax = 1e+5 * MeV;
2226  double Eem = SampleEnergy(Emin, Emax, Age);
2227 
2228  fSGammas += Weight * Eem * kTrackPerGEV / kMeterPerVEM;
2229  }
2230  } // if nGammas>0
2231 
2232  return fSMuons + fSElectrons + fSGammas;
2233 }
2234 
2235 
2236 /*
2237  See GAP note 2005-059
2238 */
2239 
2240 static double fgTriggerThetaBins [5] = { 15, 25, 35, 45, 55 };
2241 static double fgTriggerS1000Bins [4] = { 4.5, 13.5, 40.5, 121.5 };
2242 
2243 static double fgTriggerPropShalf [5] [4] = {
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 }
2249 };
2250 
2251 static double fgTriggerPropShalfError [5] [4] = {
2252  { .6, .9, .4, .2 },
2253  { .9, .5, .5, .3 },
2254  { .7, .6, .5, .2 },
2255  { .4, .5, .5, .2 },
2256  { .9, .4, .4, .2 }
2257 };
2258 
2259 double
2260 SdSimpleSim::T1TriggerProbability(double signal, double S1000, double theta)
2261 {
2262  static double n = 2.8; // or 3
2263 
2264  if (S1000 > fgTriggerS1000Bins[3]) {
2265  S1000 = fgTriggerS1000Bins[3];
2266  }
2267 
2268  if (S1000 < fgTriggerS1000Bins[0]) {
2269  S1000 = fgTriggerS1000Bins[0];
2270  }
2271 
2272  if (theta > fgTriggerThetaBins[4]) {
2273  theta = fgTriggerThetaBins[4];
2274  }
2275 
2276  if (theta < fgTriggerThetaBins[0]) {
2277  theta = fgTriggerThetaBins[0];
2278  }
2279 
2280  // ---------INFO--------------
2281  if (fVerbosity > 3) {
2282  ostringstream dbg;
2283  dbg << " pT1: " << theta << " " << S1000 << " " << signal;
2284  INFO(dbg);
2285  }
2286  // -----------------------
2287 
2288  int thetaBin;
2289  for (thetaBin = 0; thetaBin < 4; ++thetaBin) {
2290  if (theta >= fgTriggerThetaBins[thetaBin] && theta <= fgTriggerThetaBins[thetaBin+1]) {
2291  break;
2292  }
2293  }
2294 
2295  int s1000Bin;
2296  for (s1000Bin = 0; s1000Bin < 3; ++s1000Bin) {
2297  if (S1000 >= fgTriggerS1000Bins[s1000Bin] && S1000 <= fgTriggerS1000Bins[s1000Bin+1]) {
2298  break;
2299  }
2300  }
2301 
2302  double S_half_11 = fgTriggerPropShalf[thetaBin][s1000Bin];
2303  double S_half_12 = fgTriggerPropShalf[thetaBin][s1000Bin+1];
2304  double S_half_21 = fgTriggerPropShalf[thetaBin+1][s1000Bin];
2305  double S_half_22 = fgTriggerPropShalf[thetaBin+1][s1000Bin+1];
2306 
2307  double S_half_error_11 = fgTriggerPropShalfError[thetaBin][s1000Bin];
2308  double S_half_error_12 = fgTriggerPropShalfError[thetaBin][s1000Bin+1];
2309  double S_half_error_21 = fgTriggerPropShalfError[thetaBin+1][s1000Bin];
2310  double S_half_error_22 = fgTriggerPropShalfError[thetaBin+1][s1000Bin+1];
2311 
2312  // extrapolate in theta direction
2313 
2314  double delta_s1000 = (S1000 - fgTriggerS1000Bins[s1000Bin]) / (fgTriggerS1000Bins[s1000Bin+1] - fgTriggerS1000Bins[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;
2319 
2320  double delta_theta = (theta - fgTriggerThetaBins[thetaBin]) / (fgTriggerThetaBins[thetaBin+1] - fgTriggerThetaBins[thetaBin]);
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;
2323 
2324  // ---------INFO--------------
2325  if (fVerbosity > 3) {
2326  ostringstream dbg;
2327  dbg << " S_0.5 " << S_half << " " << S_half_error;
2328  INFO(dbg);
2329  }
2330  // -----------------------
2331 
2332  double p = pow(signal, n);
2333  p /= (p + pow(S_half, n));
2334  return p;
2335 }
2336 
2337 
2338 double
2340 {
2341  const double switchTriggerGPS = 795.3e6; // GPS sec, as taken from plotting data vs. time
2342 
2343  if (time.GetGPSSecond() < switchTriggerGPS)
2344  return 120. * microsecond;
2345  else
2346  return 20. * microsecond;
2347 }
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.
const double eV
Definition: GalacticUnits.h:35
int GetPrimaryParticle() const
Get the type of the shower primary particle.
Definition: ShowerSimData.h:84
unsigned int GetNPoints() const
Station Level Simulated Data
StationIterator StationsEnd()
End of all stations.
Definition: SEvent.h:59
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.
Point object.
Definition: Point.h:32
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.
Definition: SEvent.cc:81
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
Definition: BasicVector.h:254
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.
Definition: VModule.h:62
void MakeSimData()
Make station simulated data object.
RandomEngineType & GetEngine()
Definition: RandomEngine.h:32
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.
Definition: SEvent.h:39
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...
Definition: VModule.h:68
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)
Definition: SEvent/Header.h:22
void SetTime(const utl::TimeStamp &time)
Set time of the trigger.
void SetCandidate()
Set candidate station flag.
constexpr double rad
Definition: AugerUnits.h:137
bool HasSimShower() const
EventTrigger & GetTrigger()
Get the object with central trigger data, throw if n.a.
Definition: SEvent.h:148
const atm::ProfileResult & EvaluateDistanceVsSlantDepth() const
Table of distance as a function of slant depth.
const double meter
Definition: GalacticUnits.h:29
sevt::StationRecData & GetRecData()
Get station level reconstructed data.
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
static double fgTriggerS1000Bins[4]
Header file holding the SD Event Trigger class definition.
Definition: SEvent/Header.h:16
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
double pow(const double x, const unsigned int i)
double T1TriggerProbability(double signal, double S1000, double theta)
std::string GetVersionInfo(const VersionInfoType v) const
Retrieve different sorts of module version info.
Definition: VModule.cc:26
bool Noise(sevt::SEvent &sevent, const utl::TimeStamp &T0, int TankID, double TimeOffset, double TimeWindow)
void MakeTriggerData()
Make trigger data object.
const double EeV
Definition: GalacticUnits.h:34
double GetMag() const
Definition: Vector.h:58
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.
Definition: SdSimpleSim.cc:201
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.
Definition: TimeStamp.h:110
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)
constexpr double deg
Definition: AugerUnits.h:140
constexpr double MeV
Definition: AugerUnits.h:184
Interface class to access Shower Simulated parameters.
Definition: ShowerSimData.h:49
double TankIntersection(double r, double phi, double z, double theta, double TankRadius)
const atm::Atmosphere & GetAtmosphere() const
Definition: Detector.h:113
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
static double kMeterPerVEM
Definition: SdSimpleSim.cc:86
Class representing a document branch.
Definition: Branch.h:107
class to hold data at Station level
fwk::VModule::ResultFlag Init()
Initialize: invoked at beginning of run (NOT beginning of event)
Definition: SdSimpleSim.cc:102
void SetLowGainSaturation(const bool sat=true)
double GenerateNoiseStation(sevt::Station &tank, const utl::TimeStamp &T0, double TimeOffset, double TimeWindow)
constexpr double s
Definition: AugerUnits.h:163
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
Definition: BasicVector.h:206
double MoliereRadius(double temperature, double pressure, const double cosTheta)
The Moliere Radius (2 radiation length above obs-level, GAP-1998-002)
const double ns
Interface class to access the Event Trigger (T3)
Class describing the Atmospheric profile.
Definition: ProfileResult.h:25
constexpr double kPi
Definition: MathConstants.h:24
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.
Definition: Detector.h:81
const sdet::SDetector & GetSDetector() const
Definition: Detector.cc:119
bool HasTrigger() const
check whether the central trigger object exists
Definition: SEvent.h:153
void MakeTrigger()
Create the central trigger object.
Definition: SEvent.cc:102
Triple PointToLatitudeLongitudeHeight(const Point &thePoint) const
Convert Point to Lat/Long/Height.
StationIterator StationsEnd() const
End of the collection of pointers to commissioned stations.
Definition: SDetector.h:102
const atm::ProfileResult & EvaluateDepthVsHeight() const
Tabulated function giving Y=depth as a function of X=height.
double NerlingF2(double E, double a2, double s)
const double km
constexpr double g
Definition: AugerUnits.h:200
double GetEnergy() const
Get the energy of the shower primary particle.
Definition: ShowerSimData.h:89
StationIterator StationsBegin() const
Beginning of the collection of pointers to commissioned stations.
Definition: SDetector.h:97
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
Definition: SEvent.cc:65
#define WARNING(message)
Macro for logging warning messages.
Definition: ErrorLogger.h:163
void GetData(bool &b) const
Overloads of the GetData member template function.
Definition: Branch.cc:644
utl::RandomEngine & fRandomEngine
for CLHEP random nubers
Definition: SdSimpleSim.h:138
const string file
double LTP(double r, double theta, double energy)
constexpr double hertz
Definition: AugerUnits.h:153
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
Definition: SdSimpleSim.cc:87
Station & GetStation(const int stationId)
retrieve station by id throw utl::NonExistentComponentException if n.a.
Definition: SEvent.h:116
std::map< evt::ShowerSimData::ProfileType, FitParam > fProfileExtrapolation
Definition: SdSimpleSim.h:133
double GetInterval() const
Get the time interval as a double (in Auger base units)
Definition: TimeInterval.h:69
double GetRho(const CoordinateSystemPtr &coordinateSystem) const
radius r in cylindrical coordinates (distance to z axis)
Definition: BasicVector.h:263
void SetSignalStartTime(const utl::TimeStamp time)
Start time of the signal.
void MakeRecData()
Make station reconstructed data object.
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
double MinX() const
Return the minimum value for X (ordinate) stored in the profile.
Algorithm GetAlgorithm() const
constexpr double GeV
Definition: AugerUnits.h:187
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
static double fgTriggerPropShalf[5][4]
unsigned long GetGPSSecond() const
GPS second.
Definition: TimeStamp.h:124
bool HasRecData() const
Check whether station reconstructed data exists.
void SetId(const int id)
Definition: SEvent/Header.h:23
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.
Definition: SEvent.h:57
bool HasGHParameters() const
Check initialization of the Gaisser-Hillas parameters.
constexpr double cm
Definition: AugerUnits.h:117
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.
Vector object.
Definition: Vector.h:30
Detector description interface for SDetector-related data.
Definition: SDetector.h:42
Report failure to RunController, causing RunController to terminate execution.
Definition: VModule.h:64
sevt::Header & GetHeader()
Definition: SEvent.h:155
Main configuration utility.
Definition: CentralConfig.h:51
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)
Definition: Functions.h:31
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:212
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.
Definition: ErrorLogger.h:165
bool IsNoise(double TimeWindow)
constexpr double m
Definition: AugerUnits.h:121
constexpr double microsecond
Definition: AugerUnits.h:147
FitParam FitAtmosphere(const atm::ProfileResult &prof)
bool HasSEvent() const
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.
void SetCoordinates(const double r, const double zeta)
constexpr double cm2
Definition: AugerUnits.h:118

, generated on Tue Sep 26 2023.