EventGenerator.cc
Go to the documentation of this file.
1 #include "EventGenerator.h"
2 
3 #include <config.h>
4 
5 #include <fwk/CentralConfig.h>
6 #include <fwk/RunController.h>
7 #include <fwk/RandomEngineRegistry.h>
8 #include <fwk/LocalCoordinateSystem.h>
9 
10 #include <det/Detector.h>
11 
12 #include <fdet/FDetector.h>
13 #include <fdet/Eye.h>
14 
15 #include <sdet/SDetector.h>
16 #include <sdet/Station.h>
17 
18 #include <rdet/RDetector.h>
19 #include <rdet/Station.h>
20 
21 #include <evt/Event.h>
22 #include <evt/Header.h>
23 #include <evt/ShowerSimData.h>
24 #include <evt/RadioSimulation.h>
25 #include <evt/SimRadioPulse.h>
26 #include <evt/DefaultShowerGeometryProducer.h>
27 
28 #include <revt/REvent.h>
29 #include <revt/Header.h>
30 
31 #include <sevt/SEvent.h>
32 #include <sevt/Header.h>
33 #include <sevt/StationSimData.h>
34 #include <sevt/Station.h>
35 
36 #include <fevt/FEvent.h>
37 #include <fevt/Header.h>
38 
39 #include <mevt/MEvent.h>
40 #include <mevt/Header.h>
41 #include <mdet/MDetector.h>
42 #include <mdet/Counter.h>
43 #include <mevt/CounterSimData.h>
44 #include <mevt/Counter.h>
45 
46 #include <utl/AugerCoordinateSystem.h>
47 #include <utl/AugerUnits.h>
48 #include <utl/CoordinateSystem.h>
49 #include <utl/Transformation.h>
50 #include <utl/ErrorLogger.h>
51 #include <utl/Reader.h>
52 #include <utl/UTMPoint.h>
53 #include <utl/ReferenceEllipsoid.h>
54 #include <utl/Vector.h>
55 #include <utl/AxialVector.h>
56 #include <utl/PhysicalConstants.h>
57 #include <utl/RandomEngine.h>
58 #include <utl/Math.h>
59 #include <utl/String.h>
60 #include <utl/Triple.h>
61 #include <utl/AugerException.h>
62 #include <utl/GeometryUtilities.h>
63 
64 #include <boost/format.hpp>
65 
66 #include <CLHEP/Random/RandFlat.h>
67 
68 #include <cstddef>
69 #include <iostream>
70 #include <string>
71 #include <sstream>
72 #include <algorithm>
73 #include <cctype>
74 
75 #include <TH2.h>
76 #include <TFile.h>
77 
78 using namespace std;
79 using namespace utl;
80 using namespace fwk;
81 using namespace EventGeneratorOG;
82 
83 using CLHEP::RandFlat;
84 
85 
86 namespace EventGeneratorOG {
87 
88  /* workaround since uint pow10(uint) is not
89  * implemented in all standard libraries */
90  inline
91  size_t
92  MyPow10(const size_t a)
93  {
94  if (a == 0)
95  return 1;
96  if (a == 1)
97  return 10;
98  size_t result = 10;
99  for (size_t t = 1; t < a; ++t)
100  result *= 10;
101  return result;
102  }
103 
104 
107  {
108  Branch topBranch =
109  CentralConfig::GetInstance()->GetTopBranch("EventGenerator");
110 
111  Branch evtIdB = topBranch.GetChild("eventIdentifier");
112  evtIdB.GetChild("libraryIdentifier").GetData(fLibraryIdentifier);
113  evtIdB.GetChild("format").GetData(fFormat);
114  evtIdB.GetChild("sdIdFormat").GetData(fSdIdFormat);
115 
116  if (topBranch.GetChild("useRadioCorePosition")) {
117  topBranch.GetChild("useRadioCorePosition").GetData(fUseRadioCorePosition);
118  topBranch.GetChild("useRadioEventTime").GetData(fUseRadioEventTime);
119  ostringstream info;
120  info << "\n"
121  "\tUsage of radio core position is set to " << fUseRadioCorePosition << "\n"
122  "\tUsage of radio event time is set to " << fUseRadioEventTime;
123  INFO(info);
124  }
125 
126  string mode;
127  topBranch.GetChild("mode").GetData(mode);
128  if (mode == "SD")
129  fMode = eSD;
130  else if (mode == "FD")
131  fMode = eFD;
132  else if (mode == "Hy")
133  fMode = eHy;
134  else if (mode == "MD")
135  fMode = eMD;
136  else if (mode == "XD") // eXtended SD (SD+MD)
137  fMode = eXD;
138  else if (mode == "XH") // eXtended Hybrid (SD+MD+FD)
139  fMode = eXH;
140  else
141  INFO("Undefined event type...");
142 
143  // Set a ficticious event time
144  Branch eventTimeB = topBranch.GetChild("eventTime");
145  if (eventTimeB) {
146 
147  fSampleTimes = false;
148  eventTimeB.GetData(fStartDate);
149 
150  } else {
151 
152  fSampleTimes = true;
153  Branch timeIntervalB = topBranch.GetChild("timeInterval");
154 
155  fTimeOrdered = false;
156  fTimeRandomized = true;
157  Branch timeOrderedB = timeIntervalB.GetChild("timeOrdered");
158  if (timeOrderedB) {
159  fTimeOrdered = true;
160  timeOrderedB.GetChild("nEvents").GetData(fNEvents);
161  Branch timeRandomizedB = timeOrderedB.GetChild("timeRandomized");
162  if (timeRandomizedB)
163  timeRandomizedB.GetData(fTimeRandomized);
164  }
165  timeIntervalB.GetChild("startTime").GetData(fStartDate);
166  timeIntervalB.GetChild("endTime").GetData(fEndDate);
167 
168  }
169 
170  // Flags to signal data and/or component invalidation.
171  Branch invalidateDataB = topBranch.GetChild("invalidateData");
172  Branch invalidateCompB = topBranch.GetChild("invalidateComponents");
173  // Our defaults:
174  fInvalidateData = true;
175  fInvalidateComponents = true;
176  // Load.
177  INFO("Configuring invalidation flags.");
178  if (invalidateDataB) {
179  INFO("Loading invalidate data flag from branch.");
180  invalidateDataB.GetData(fInvalidateData);
181  }
182  if (invalidateCompB) {
183  INFO("Loading invalidate components flag from branch.");
184  invalidateCompB.GetData(fInvalidateComponents);
185  }
186  if (fInvalidateData)
187  INFO("Detector data will be invalidated on update.");
188  if (fInvalidateComponents)
189  INFO("Detector components will be invalidated on update.");
190  // Ready to do...
191  det::Detector::GetInstance().Update(fStartDate, fInvalidateData, fInvalidateComponents);
192 
193  // Data to randomize the core position
194  Branch coreRandomizationB = topBranch.GetChild("coreRandomization");
195 
196  // Case of Air Shower MC core positions
197  Branch useCoresFromAirShowerMCB = coreRandomizationB.GetChild("useCoresFromAirShowerMC");
198 
199  // Case of array-centric core randomization
200  Branch centerOfTileB = coreRandomizationB.GetChild("centerOfTile");
201  Branch listOfCorePositionsB = coreRandomizationB.GetChild("listOfCorePositions");
202  Branch useRandomStationB = coreRandomizationB.GetChild("useRandomStation");
203  Branch useRandomInfillStationB = coreRandomizationB.GetChild("useRandomInfillStation");
204  Branch sphereCenterB = coreRandomizationB.GetChild("sphereCenter");
205 
206  fUseRandomInfillStation = false;
207  fUseRandomStation = false;
208 
209  if (useCoresFromAirShowerMCB) { // use cores from CORSIKA/EAS-sim
210 
211  fUseSimCores = true;
212  fSimCoreCount = 0;
213 
214  } else if (useRandomStationB) { // choose random stations of array
215 
216  useRandomStationB.GetData(fUseRandomStation);
217 
218  if (useRandomInfillStationB) // choose random stations of array
219  useRandomInfillStationB.GetData(fUseRandomInfillStation);
220 
221  } else if (centerOfTileB) { // take specific center of tile
222 
223  Branch sizeTileB = coreRandomizationB.GetChild("sizeOfTile");
224  sizeTileB.GetChild("deltaNorthing").GetData(fDeltaNorthing);
225  sizeTileB.GetChild("deltaEasting").GetData(fDeltaEasting);
226 
227  // Tile center can be specified by either UTM coordinates
228  // or station number.
229  Branch stationAtCenterB = centerOfTileB.GetChild("stationAtCenter");
230  if (stationAtCenterB) { // center on station
231  int stationId;
232  stationAtCenterB.GetData(stationId);
233 
234  const sdet::Station& theStat =
235  det::Detector::GetInstance().GetSDetector().GetStation(stationId);
236 
237  const UTMPoint theUTMPoint =
238  UTMPoint(theStat.GetPosition(), ReferenceEllipsoid::eWGS84);
239  fNorthing = theUTMPoint.GetNorthing();
240  fEasting = theUTMPoint.GetEasting();
241  fAltitude = theUTMPoint.GetHeight();
242  fZone = theUTMPoint.GetZone();
243  fBand = theUTMPoint.GetBand();
244  } else { // center on UTM point
245  centerOfTileB.GetChild("northing").GetData(fNorthing);
246  centerOfTileB.GetChild("easting").GetData(fEasting);
247  if (centerOfTileB.GetChild("altitude"))
248  centerOfTileB.GetChild("altitude").GetData(fAltitude);
249  else {
250  centerOfTileB.GetChild("height").GetData(fAltitude);
251  WARNING("keyword 'height' is deprecated in specification of core position. Please use 'altitude'.");
252  }
253  centerOfTileB.GetChild("zone").GetData(fZone);
254  centerOfTileB.GetChild("band").GetData(fBand);
255  }
256 
257  } else if (listOfCorePositionsB) {
258 
259  for (Branch coreB = listOfCorePositionsB.GetFirstChild(); coreB; coreB = coreB.GetNextSibling()) {
260  const double nor = coreB.GetChild("northing").Get<double>();
261  const double eas = coreB.GetChild("easting").Get<double>();
262  double alt = 0;
263  if (coreB.GetChild("altitude"))
264  coreB.GetChild("altitude").GetData(alt);
265  else {
266  coreB.GetChild("height").GetData(alt);
267  WARNING("keyword 'height' is deprecated in specification of core position. Please use 'altitude'.");
268  }
269  const int zone = coreB.GetChild("zone").Get<int>();
270  const char band = coreB.GetChild("band").Get<char>();
271  fCorePositions.push_back(boost::tuple<double, double, double, int, char>(nor, eas, alt, zone, band));
272  }
273 
274  fCorePositionsIt = fCorePositions.begin();
275 
276  } else if (sphereCenterB) {
277 
278  fInSphere = true;
279 
280  coreRandomizationB.GetChild("sphereRadius").GetData(fSphereRadius);
281  coreRandomizationB.GetChild("skipUpgoing").GetData(fSkipUpgoing);
282  coreRandomizationB.GetChild("limitRp").GetData(fLimitRp);
283 
284  Branch sphereCenterB = coreRandomizationB.GetChild("sphereCenter");
285  const double nor = sphereCenterB.GetChild("northing").Get<double>();
286  const double eas = sphereCenterB.GetChild("easting").Get<double>();
287  double alt = 0;
288  if (sphereCenterB.GetChild("altitude"))
289  sphereCenterB.GetChild("altitude").GetData(alt);
290  else {
291  sphereCenterB.GetChild("height").GetData(alt);
292  WARNING("keyword 'height' is deprecated in specification of core position. Please use 'altitude'.");
293  }
294  const int zone = sphereCenterB.GetChild("zone").Get<int>();
295  const char band = sphereCenterB.GetChild("band").Get<char>();
296  fSphereCenter = boost::tuple<double, double, double, int, char>(nor, eas, alt, zone, band);
297 
298  } else { // Case of eye-centric core randomization
299 
300  fEyeCentric = true;
301 
302  coreRandomizationB.GetChild("eye").GetData(fEyeid);
303  coreRandomizationB.GetChild("telescope").GetData(fTelid);
304  coreRandomizationB.GetChild("maxdist").GetData(fMaxDist);
305  fMinDist = 0;
306  if (coreRandomizationB.GetChild("mindist"))
307  coreRandomizationB.GetChild("mindist").GetData(fMinDist);
308  if (coreRandomizationB.GetChild("altitude"))
309  coreRandomizationB.GetChild("altitude").GetData(fAltitude);
310  else {
311  coreRandomizationB.GetChild("height").GetData(fAltitude);
312  WARNING("keyword 'height' is deprecated in specification of core position. Please use 'altitude'.");
313  }
314  string enDep;
315  coreRandomizationB.GetChild("rMaxEnergyDependent").GetData(enDep);
316  fRMaxEnergyDependent = (enDep == "yes");
317  coreRandomizationB.GetChild("deltaphi").GetData(fDeltaPhi);
318  coreRandomizationB.GetChild("geometryCherenkovHECO").GetData(fGeometryCheckCherenkovHECO);
319  if (fRMaxEnergyDependent && fGeometryCheckCherenkovHECO) {
320  WARNING("geometryCherenkovHECO is not compatible with rMaxEnergyDependent, geometryCherenkovHECO switched OFF");
321  fGeometryCheckCherenkovHECO = false;
322  }
323  if (fGeometryCheckCherenkovHECO && coreRandomizationB.GetChild("maxVAfileHECO")) {
324  string f;
325  coreRandomizationB.GetChild("maxVAfileHECO").GetData(f);
326  TFile file(f.c_str());
327  fMaxVA = (TH2D*)file.Get("hMaxVA");
328  fMaxVA->SetDirectory(0);
329  file.Close();
330  }
331 
332  }
333 
334  fRandomEngine = &RandomEngineRegistry::GetInstance().Get(RandomEngineRegistry::eDetector);
335 
336  // generate new random times
337  if (fSampleTimes && fTimeOrdered) {
338 
339  INFO("generate new times and sort ascending .... ");
340  const double intervalLength = (fEndDate - fStartDate).GetInterval();
341  const auto re = &fRandomEngine->GetEngine();
342  for (int i = 0; i < fNEvents; ++i) {
343  if (fTimeRandomized)
344  fTimeList.push_back(RandFlat::shoot(re, 0, 1) * intervalLength);
345  else
346  fTimeList.push_back(i * intervalLength / fNEvents);
347  }
348 
349  // sort with ascending time
350  fTimeList.sort();
351 
352  }
353 
354  // final info output
355  ostringstream info;
356  info << "Parameters:\n"
357  " library identifier: " << fLibraryIdentifier << "\n"
358  " Id format: " << fFormat << "\n"
359  " SD Id format: " << fSdIdFormat[0] << " " << fSdIdFormat[1] << "\n"
360  " event init mode: ";
361  switch (fMode) {
362  case eSD: info << "SD\n"; break;
363  case eFD: info << "FD\n"; break;
364  case eHy: info << "Hybrid\n"; break;
365  case eMD: info << "MD\n"; break;
366  case eXD: info << "eXtended SD (SD + MD)\n"; break;
367  case eXH: info << "eXtended Hybrid (SD + MD + FD)\n"; break;
368  default: info << "unknown\n"; break;
369  }
370  if (fSampleTimes) {
371  info << " -- sample event times from period -- \n"
372  " start period: " << fStartDate << "\n"
373  " end period: " << fEndDate << "\n"
374  " time pre-ordered: " << (fTimeOrdered ? "yes" : "no");
375  if (fTimeOrdered)
376  info << "; number of events: " << fNEvents;
377  info << "; time randomized: " << (fTimeRandomized ? "yes" : "no")
378  << '\n';
379  } else {
380  info << " event time: " << fStartDate << '\n';
381  }
382  if (fUseSimCores) {
383  info << " -- use cores from EAS simulation program -- \n";
384  } else if (fInSphere) {
385  info << " -- shere volume centric option-- \n"
386  " sphere radius: " << fSphereRadius/m << " m\n"
387  " skip upgoing: " << fSkipUpgoing << " m\n"
388  " maximum Rp limited: " << fLimitRp << " m\n"
389  " sphere center northing: " << fSphereCenter.get<0>() << " m\n"
390  " sphere center easting: " << fSphereCenter.get<1>() << " m\n"
391  " sphere center altitude: " << fSphereCenter.get<2>() << " m\n"
392  " sphere center zone: " << fSphereCenter.get<3>() << "\n"
393  " sphere center band: " << fSphereCenter.get<4>();
394  } else if (fEyeCentric) {
395  info << " -- eye centric core randomization -- \n"
396  " eye Id: " << fEyeid << "\n"
397  " telescope Id: " << fTelid << "\n"
398  " delta phi: " << fDeltaPhi/deg << "deg\n"
399  " min distance: " << fMinDist/km << "km\n"
400  " max distance: " << fMaxDist/km << "km"
401  << (fRMaxEnergyDependent ? " (energy dependent)" : "") << "\n"
402  << (fGeometryCheckCherenkovHECO ? "Cherenkov HECO geometry cut\n" : "") <<
403  " altitude: " << fAltitude/m << 'm';
404  } else {
405  if (fUseRandomStation) {
406  if (fUseRandomInfillStation)
407  info << " -- cores around random infill station --";
408  else
409  info << " -- cores around random station --";
410  } else if (!fCorePositions.empty()) {
411  info << " -- cores from XML list --\n"
412  " number of cores: " << fCorePositions.size();
413  } else {
414  info << " -- array centric core randomization -- \n"
415  " northing: " << fNorthing << "\n"
416  " easting: " << fEasting << "\n"
417  " altitude: " << fAltitude;
418  }
419  }
420 
421  INFO(info);
422 
423  return eSuccess;
424  }
425 
426 
428  EventGenerator::Run(evt::Event& event)
429  {
430  /*
431  * RFG If no shower loaded then this flag is set, and
432  * then only the time is set; but we desire (for AMIGA simulations with
433  * particle injector) to also init the event structures.
434  */
435  const bool justSetDetectorTimeForMuonCalibrationLoop =
436  !event.HasSimShower() && fMode != eMD && fMode != eXD && fMode != eXH;
437 
438  TimeStamp eventTime = fStartDate;
439 
440  const auto re = &fRandomEngine->GetEngine();
441 
442  if (fSampleTimes) {
443 
444  if (fTimeOrdered) {
445 
446  if (fTimeList.empty()) {
447  INFO("Maximum number of events generated in time interval. Stopping.");
448  return eBreakLoop;
449  }
450 
451  eventTime = fStartDate + TimeInterval(fTimeList.front());
452 
453  // only if we really want to move to the next event, we get rid of this entry
454  if (!justSetDetectorTimeForMuonCalibrationLoop)
455  fTimeList.pop_front();
456 
457  } else {
458 
459  // for muon calibration loop any time is good enough, so don't consider special case here
460  const double intervalLength = (fEndDate - fStartDate).GetInterval();
461  eventTime = fStartDate + TimeInterval(RandFlat::shoot(re, 0, 1) * intervalLength);
462 
463  }
464  }
465 
466  if (fUseRadioEventTime) {
467  if (event.HasSimShower()) {
468  const evt::ShowerSimData& shower = event.GetSimShower();
469  const evt::RadioSimulation& rSim = shower.GetRadioSimulation();
470  eventTime = rSim.GetEventTime();
471 
472  ostringstream rdout;
473  rdout << "Setting event time to radio event time " << eventTime;
474  INFO(rdout);
475  } else {
476  throw utl::AugerException("UseRadioEventTime is set to true but no SimShower is available! Abort ...");
477  }
478  }
479 
480  /*
481  Set detector time
482  this needs to be executed with every call of the Module, because this has to be done
483  for the SD muon calibration loop as well, as for pure FD simultion and others.
484 
485  Anyway this is not strictly dependant on muon detection.
486  Use also the flags for configuring the invalidation behaviour.
487  */
488  det::Detector::GetInstance().Update(eventTime, fInvalidateData, fInvalidateComponents);
489 
490  // tcp. this should be a separate module, not hotwired for special cases
491  if (justSetDetectorTimeForMuonCalibrationLoop) {
492 
493  /*
494  This part of the code is only executed for SD simulation BEFORE the actual SD detector simulation
495  starts. It is needed to bring the detector into an well defined state before the muon calibration
496  loop.
497  Since 06/2009 this part of the code is also utilized for the Fd-DrumCalibration simulation loop.
498  */
499  INFO("SimShower does not exist, only detector time will be set.");
500 
501  if (event.HasSEvent() || event.HasFEvent() || event.HasMEvent()) {
502  ostringstream err;
503  err << "Something in your ModuleSequence must be wrong! Your event data structure is corrupt (hasSd="
504  << event.HasSEvent() << ", hasFD=" << event.HasFEvent()
505  << ", hasMD=" << event.HasMEvent() << ")!";
506  ERROR(err);
507  return eFailure;
508  }
509 
510  // init SD event structure
511  if (fMode == eSD || fMode == eHy || fMode == eXD || fMode == eXH) { // If SD+MD or SD+MD+FD needs to initialize SD part
512  INFO("SD event is created for calibration loop.");
513  event.MakeSEvent();
514  }
515 
516  // init FD event structure
517  if (fMode == eFD || fMode == eHy || fMode == eXH) { // SD+MD+FD needs to initialize SD part
518  INFO("FD event is created for drum calibration loop.");
519  event.MakeFEvent();
520  }
521 
522  } else {
523 
524  /*
525  This part of the code has to
526  - initialise the event data structures fo FD/SD/Hy simulations.
527  - set a random core
528  - set the event time
529  */
530 
531  const ReferenceEllipsoid& e = ReferenceEllipsoid::GetWGS84();
532 
533  // If SD+MD or SD+MD+FD needs to initialize SD part
534  if (!event.HasSEvent() && (fMode == eSD || fMode == eHy || fMode == eXD || fMode == eXH))
535  event.MakeSEvent();
536 
537  if (!event.HasFEvent() && (fMode == eFD || fMode == eHy || fMode == eXH))
538  event.MakeFEvent();
539 
540  if (!event.HasMEvent() && (fMode == eMD || fMode == eXD || fMode == eXH))
541  event.MakeMEvent();
542 
543 #warning RU: I think this should throw exception here. SimShower must already exists in EventGenerator. Check logic!!!!!
544  if (!event.HasSimShower())
546 
547  evt::ShowerSimData& shower = event.GetSimShower();
548 
549  if (shower.GetNSimCores() > 0 && !fUseSimCores) {
550  const string err =
551  "You are using a shower with pre-defined core locations (e.g. AUGERHIT) but try to overwrite them. "
552  "This is not consistent. Very likely your simulation is garbage...";
553  ERROR(err); // ... maybe the user knows what he is doing ... don't throw
554  //throw utl::AugerException(err);
555  }
556 
557  if (!shower.HasTimeStamp())
558  shower.MakeTimeStamp(eventTime);
559 
560  if (fUseRandomStation) {
561 
562  const sdet::SDetector& det = det::Detector::GetInstance().GetSDetector();
563  std::vector<int> stationList;
564  // make a vector of stations
565  for (const auto& s : det.StationsRange()) {
566  if (fUseRandomInfillStation) {
567  if (s.IsInGrid(sdet::SDetectorConstants::eInfill750) && GetInfillCrown(s).size() > 5)
568  stationList.push_back(s.GetId());
569  } else if (s.IsInGrid() && s.GetCrown(1).size() == 6)
570  stationList.push_back(s.GetId());
571  }
572 
573  if (stationList.empty())
574  throw utl::AugerException("Asked to simulate around a random station but I get an empty list of stations.");
575 
576  const int nrOfStations = stationList.size();
577  const int stationPos = int(RandFlat::shoot(re, 0, 1) * nrOfStations);
578  const int stationId = stationList[stationPos];
579  const sdet::Station& stat = det.GetStation(stationId);
580 
581  const UTMPoint utm(stat.GetPosition(), ReferenceEllipsoid::eWGS84);
582  fNorthing = utm.GetNorthing();
583  fEasting = utm.GetEasting();
584  fAltitude = utm.GetHeight();
585  fZone = utm.GetZone();
586  fBand = utm.GetBand();
587  fStationId = stationId;
588  }
589 
590  bool csDefined = false;
591  CoordinateSystemPtr coreCS; // the new core coordinate system
592 
593  double newNorthingCore = 0;
594  double newEastingCore = 0;
595  double newAltitudeCore = 0;
596  if (fUseSimCores) {
597  if (fSimCoreCount >= shower.GetNSimCores()) {
598  fSimCoreCount = 0;
599  return eBreakLoop;
600  }
601  const utl::Point core = shower.GetSimCore(fSimCoreCount);
602  coreCS = AugerCoordinateSystem::Create(core, e, e.GetECEF());
603  csDefined = true;
604  {
605  const UTMPoint coreUTM(core, e);
606  newNorthingCore = coreUTM.GetNorthing();
607  newEastingCore = coreUTM.GetEasting();
608  }
609  ++fSimCoreCount;
610  } else if (fInSphere) {
611  boost::tie(newEastingCore, newNorthingCore, newAltitudeCore) = GenerateSphereCentricCore(shower);
612  } else if (fEyeCentric) {
613  boost::tie(newEastingCore, newNorthingCore) = GenerateEyeCentricCore(shower.GetEnergy());
614  newAltitudeCore = fAltitude;
615  } else {
616  if (!fCorePositions.empty()) { // use list of cores
617  if (fCorePositionsIt == fCorePositions.end()) {
618  if (!fUseRadioCorePosition) {
619  INFO("Reached last requested core position in the list. Terminating the run.");
620  return eBreakLoop;
621  }
622  } else
623  boost::tie(newEastingCore, newNorthingCore, newAltitudeCore) = GenerateArrayCentricListedCore();
624  } else {
625  if (fUseRandomStation) {
626  boost::tie(newEastingCore, newNorthingCore) = GenerateArrayCentricRandomizedCoreAroundRandomStation();
627  newAltitudeCore = fAltitude;
628  } else {
629  boost::tie(newEastingCore, newNorthingCore) = GenerateArrayCentricRandomizedCore();
630  newAltitudeCore = fAltitude;
631  }
632  }
633  }
634  if (!csDefined) {
635  const UTMPoint newPosition(newNorthingCore, newEastingCore, newAltitudeCore, fZone, fBand, e);
636  coreCS = AugerCoordinateSystem::Create(newPosition.GetPoint(), e, e.GetECEF());
637  csDefined = true;
638  }
639 
640  // Set the core position defined in the .reas file of the CoREAS simulation
641  if (fUseRadioCorePosition) {
642  ostringstream rdout;
643 
644  evt::RadioSimulation& rSim = shower.GetRadioSimulation();
645 
646  // /*
647  // For the simulation of the radio emission from air showers the positions of the "to-be-simulated" pulses, i.e., antennas,
648  // have to be provided. Thus the simulated radio pulses are just valid for this positions (relative to the core). To match
649  // the location of actuall antennas, a core can be defind in the .reas file of the CoREAS simulations. However this value can be
650  // wrong (as it is for the RdObserver_v1r3 library). Here we calculate a average offset between the positions of simulated
651  // pulses and the detector stations and correct the core position.
652  // */
653  // utl::Vector averageOffset = GetCoreShiftForRadioSimulation(rSim);
654  // rdout << "Average offset between simulated pulses and radio detector stations: "
655  // << averageOffset.GetX(coreSys) / meter << " m, " << averageOffset.GetY(coreSys) / meter
656  // << " m, " << averageOffset.GetZ(coreSys) / meter << " m. Correcting shower core accordingly.";
657  // rSim.SetCorePosition(rSim.GetCorePosition() + averageOffset);
658  // utl::CoordinateSystemPtr coreSysNew = rSim.GetLocalCoordinateSystem();
659 
660  shower.MakeGeometry(Point(0,0,0, rSim.GetLocalCoordinateSystem()));
661 
662  const utl::CoordinateSystemPtr refCS = det::Detector::GetInstance().GetReferenceCoordinateSystem();
663  const auto& core = shower.GetPosition();
664  rdout << "Set core position to radio core position ("
665  << core.GetX(refCS)/m << ", " << core.GetY(refCS)/m << ", " << core.GetZ(refCS)/m << ") m "
666  "in reference CS (usually PampaAmarilla)";
667  INFO(rdout);
668  } else {
669  // This throws an assert if geometry already exists. This should NOT be the case here.
670  const utl::Point core(0,0,0, coreCS);
671  shower.MakeGeometry(core);
672 
673  // After core was established set in RadioSimulation
674  if (shower.HasRadioSimulation())
675  shower.GetRadioSimulation().SetCorePosition(core);
676  }
677 
678  // Create the headers for the Event, SEvent and FEvent
679  static string showerRunId;
680  static int showerNumber = -1;
681  // reset counter on change
682  if (showerRunId != shower.GetShowerRunId() || showerNumber != shower.GetShowerNumber())
683  fEventNumber = 0;
684  showerRunId = shower.GetShowerRunId();
685  showerNumber = shower.GetShowerNumber();
686  ++fEventNumber;
687 
688  const string id =
689  (boost::format(fFormat) % fLibraryIdentifier % showerRunId % showerNumber % fEventNumber).str();
690 
691  evt::Header& header = event.GetHeader();
692  header.SetId(id);
693  header.SetTime(eventTime);
694 
695  // Create a purely numerical id for SEvent and FEvent
696  // headers, so that if for some reason the
697  // event is written in CDAS or FDAS format, at least
698  // there will be some sort of id present.
699  const size_t showerNumberMax = MyPow10(fSdIdFormat[0]);
700  const size_t useMax = MyPow10(fSdIdFormat[1]);
701  stringstream runNumberStream;
702  for (const auto& c : showerRunId)
703  if ('0' <= c && c <= '9')
704  runNumberStream << char(c);
705  size_t runNumber = 0;
706  runNumberStream >> runNumber;
707  // this fails if "runNumber" has too large value as e.g. in CONEX (runnumber = seed)
708  const int numericalId =
709  runNumber * showerNumberMax * useMax +
710  (showerNumber % showerNumberMax) * useMax +
711  (fEventNumber % useMax);
712 
713  if (fMode == eSD || fMode == eHy || fMode == eXD || fMode == eXH) { // If SD+MD or SD+MD+FD needs to initialize SD part
714  sevt::Header& sHeader = event.GetSEvent().GetHeader();
715  sHeader.SetId(numericalId);
716  sHeader.SetTime(eventTime);
717  }
718 
719  if (fMode == eFD || fMode == eHy || fMode == eXH) {
720  fevt::Header& fHeader = event.GetFEvent().GetHeader();
721  fHeader.SetId(numericalId);
722  fHeader.SetTime(eventTime);
723  }
724  /*
725  * So far for AMIGA the event generator is just to setup/update times.
726  * Later something could be done to position the shower near some counter
727  * or module, nevertheless the current strategies for putting the core
728  * near a surface tank may be enough, give the link between tanks
729  * and counters.
730  */
731  if (fMode == eMD || fMode == eXD || fMode == eXH) {
732  mevt::Header& mHeader = event.GetMEvent().GetHeader();
733  mHeader.SetId(numericalId);
734  mHeader.SetTime(eventTime);
735  }
736 
737  ostringstream info;
738  info << "generated event '" << id << "', "
739  "northing = " << setprecision(8) << newNorthingCore << ", "
740  "easting = " << newEastingCore;
741  if (fUseRandomStation)
742  info << " (" << "around station " << fStationId << ')';
743  INFO(info);
744 
745  if (fMode == eSD || fMode == eHy || fMode == eXD || fMode == eXH)
746  FlagHoleStations(event);
747  }
748 
749  ++RunController::GetInstance().GetRunData().GetNamedCounters()["EventGenerator/GeneratedEvents"];
750 
751  if ((fSkipUpgoing && fUpgoingShower) || (fLimitRp && fRpTooLarge)) {
752  return eContinueLoop;
753  } else {
754  return eSuccess;
755  }
756  }
757 
758 
760  EventGenerator::Finish()
761  {
762  // check for successful <timeInterval> sampling
763  if (fSampleTimes && fTimeOrdered && !fTimeList.empty()) {
764 
765  const int nRemains = fTimeList.size();
766 
767  ostringstream err;
768  err << "\n\n"
769  " **********************************************************************************************\n"
770  " *\n"
771  " * sampling " << fNEvents << " time" << String::Plural(fNEvents) << " from time interval NOT successful!\n"
772  " *\n"
773  " * specified period from: " << fStartDate << "\n"
774  " * to: " << fEndDate << "\n"
775  " *\n"
776  " * stopped after " << (fNEvents-nRemains) << " event" << String::Plural(fNEvents-nRemains) << "!"
777  " Unprocessed " << nRemains << " event" << String::Plural(nRemains) << "!\n"
778  " *\n"
779  " * Since events are generated after beeing ordered in time no events have been issued\n"
780  " * from: " << (fStartDate + TimeInterval(fTimeList.front())) << "\n"
781  " * to: " << fEndDate << "\n"
782  " *\n"
783  " * List of missing events:\n";
784  int iMiss = 0;
785  for (const auto& t : fTimeList)
786  err << " * - Missing event No " << (++iMiss) << " at time " << (fStartDate + TimeInterval(t)) << '\n';
787 
788  err << " *\n"
789  " * Please read EventGenerator documentation to learn how to use <timeInterval> properly\n"
790  " *\n"
791  " **********************************************************************************************\n"
792  "\n\n";
793 
794  ERROR(err);
795 
796  }
797 
798  return eSuccess;
799  }
800 
801 
802  boost::tuple<double, double>
803  EventGenerator::GenerateArrayCentricRandomizedCore()
804  {
805  const auto re = &fRandomEngine->GetEngine();
806  const double newEastingCore = fEasting + RandFlat::shoot(re, -0.5, 0.5) * fDeltaEasting;
807  const double newNorthingCore = fNorthing + RandFlat::shoot(re, -0.5, 0.5) * fDeltaNorthing;
808 
809  return boost::tuple<double, double>(newEastingCore, newNorthingCore);
810  }
811 
812 
815  {
817  const double gridSize = 750;
818  const sdet::SDetector& det = det::Detector::GetInstance().GetSDetector();
819  for (const auto& s : det.StationsRange()) {
820  if (s.IsInGrid(sdet::SDetectorConstants::eInfill750) &&
821  s.GetId() != centralStation.GetId() &&
822  (s.GetPosition() - centralStation.GetPosition()).GetMag() < 1.5*gridSize)
823  stations.push_back(s.GetId());
824  }
825  return stations;
826  }
827 
828 
829  // This function is meant to replace the next function: GenerateArrayCentricRandomizedCoreAroundRandomStation
830  boost::tuple<double, double>
831  EventGenerator::GenerateCoreAroundStation()
832  {
833  const ReferenceEllipsoid& e = ReferenceEllipsoid::GetWGS84();
834 
835  fDeltaNorthing = 2000*meter;
836  fDeltaEasting = 2000*meter;
837 
838  const sdet::SDetector& detector = det::Detector::GetInstance().GetSDetector();
839  const sdet::Station& centralStation = detector.GetStation(fStationId);
840  const Point& center = centralStation.GetPosition();
841 
843  if (!fUseRandomInfillStation)
844  stations = centralStation.GetCrown(1);
845  else {
846  // find the infill crown instead
847  stations = GetInfillCrown(centralStation);
848  }
849 
850  double eastingCore = 0;
851  double northingCore = 0;
852  bool in = false;
853  do {
854  const auto re = &fRandomEngine->GetEngine();
855  eastingCore = fEasting + RandFlat::shoot(re, -0.5, 0.5)*fDeltaEasting;
856  northingCore = fNorthing + RandFlat::shoot(re, -0.5, 0.5)*fDeltaNorthing;
857 
858  const UTMPoint utmPosition(northingCore, eastingCore, fAltitude, fZone, fBand, e);
859  const Vector randomVector = utmPosition.GetPoint(center.GetCoordinateSystem()) - center;
860 
861  in = true;
862  for (const auto id : stations) {
863  const Vector crownStationVector = detector.GetStation(id).GetPosition() - center;
864  in = in && (crownStationVector*randomVector < 0.5*(crownStationVector*crownStationVector));
865  }
866  } while (!in);
867 
868  return boost::tuple<double, double>(eastingCore, northingCore);
869  }
870 
871 
872  boost::tuple<double, double>
873  EventGenerator::GenerateArrayCentricRandomizedCoreAroundRandomStation()
874  {
875  const ReferenceEllipsoid& e = ReferenceEllipsoid::GetWGS84();
876 
877  fDeltaNorthing = 2000*meter;
878  fDeltaEasting = 2000*meter;
879 
880  const double minAngle = 2*utl::kPi - 0.1;
881  const double maxAngle = 2*utl::kPi + 0.1;
882 
883  const sdet::SDetector& detector = det::Detector::GetInstance().GetSDetector();
884  const sdet::Station& station = detector.GetStation(fStationId);
885  sdet::Station::StationIdCollection stations = station.GetCrown(1);
886  if (fUseRandomInfillStation) // find the infill crown instead
887  stations = GetInfillCrown(station);
888 
889  double eastingCore = 0;
890  double northingCore = 0;
891  double totalAngle = 0;
892  do {
893 
894  const auto re = &fRandomEngine->GetEngine();
895  // these numbers have to be optimised
896  eastingCore = fEasting + RandFlat::shoot(re, -0.5, 0.5)*fDeltaEasting;
897  northingCore = fNorthing + RandFlat::shoot(re, -0.5, 0.5)*fDeltaNorthing;
898 
899  const UTMPoint position(northingCore, eastingCore, fAltitude, fZone, fBand, e);
900 
901  const Point& center = station.GetPosition();
902  const CoordinateSystemPtr& coord = center.GetCoordinateSystem();
903 
904  const CoordinateSystemPtr localCS = LocalCoordinateSystem::Create(center);
905 
906  const Point hittingPosition = position.GetPoint(coord);
907 
908  Vector stVector0 = center - hittingPosition;
909  stVector0.Normalize();
910 
911  int firstId = 0;
912  int secondId = 0;
913  double firstAngle = utl::kPi;
914  double secondAngle = utl::kPi;
915 
916  // find the neighbours
917  for (const auto id : stations) {
918  const Point& pos = detector.GetStation(id).GetPosition();
919  const Vector stVector = Normalized(center - pos);
920  const double angle = acos(stVector * stVector0);
921  if (angle <= secondAngle) {
922  if (angle < firstAngle) {
923  secondAngle = firstAngle;
924  secondId = firstId;
925  firstAngle = angle;
926  firstId = id;
927  } else {
928  secondAngle = angle;
929  secondId = id;
930  }
931  }
932  }
933 
934  // finished finding the neighbours
935 
936  const Vector st2First = detector.GetStation(firstId).GetPosition() - center;
937  const Vector st2Second = detector.GetStation(secondId).GetPosition() - center;
938 
939  const AxialVector axFirst = Normalized(Cross(st2First, st2Second));
940  // perpendicular vectors
941  const Vector v1 = Normalized(Cross(axFirst, st2First));
942  const Vector v2 = Normalized(Cross(axFirst, st2Second));
943 
944  // define the perpendicular lines
945  const double dist = 100;
946  const Point zero(0,0,0, localCS);
947  const Point p1 = zero + 0.5 * st2First;
948  const Point p11 = p1 + dist * v1;
949  const Point p2 = zero + 0.5 * st2Second;
950  const Point p22 = p2 + dist * v2;
951 
952  const utl::Triple trip1 = p1.GetCoordinates(localCS);
953  const utl::Triple trip11 = p11.GetCoordinates(localCS);
954  const utl::Triple trip2 = p2.GetCoordinates(localCS);
955  const utl::Triple trip22 = p22.GetCoordinates(localCS);
956  // first perp line
957  const double x1 = trip1.get<0>();
958  const double y1 = trip1.get<1>();
959  const double x2 = trip11.get<0>();
960  const double y2 = trip11.get<1>();
961  // second perp line
962  const double x3 = trip2.get<0>();
963  const double y3 = trip2.get<1>();
964  const double x4 = trip22.get<0>();
965  const double y4 = trip22.get<1>();
966  // two line intersection
967  const double denominator = (x1 - x2)*(y3 - y4) - (x3 - x4)*(y1 - y2);
968  const double nominatorX = (x1*y2 - x2*y1)*(x3 - x4) - (x3*y4 - x4*y3)*(x1 - x2);
969  const double finalPointX = nominatorX / denominator;
970  const double nominatorY = (x1*y2 - x2*y1)*(y3 - y4) - (x3*y4 - x4*y3)*(y1 - y2);
971  const double finalPointY = nominatorY / denominator;
972 
973  const Point middlePoint(finalPointX, finalPointY, 0.5*(trip1.get<2>() + trip2.get<2>()), localCS);
974  const Point hittingPosition1 = position.GetPoint(localCS);
975  const Vector x0cm = Normalized(center - hittingPosition1);
976  const Vector x1cm = Normalized(p2 - hittingPosition1);
977  const Vector x2cm = Normalized(middlePoint - hittingPosition1);
978  const Vector x3cm = Normalized(p1 - hittingPosition1);
979 
980  totalAngle = acos(x0cm*x1cm) + acos(x1cm*x2cm) + acos(x2cm*x3cm) + acos(x3cm*x0cm);
981 
982  } while (totalAngle < minAngle || totalAngle > maxAngle);
983 
984  return boost::tuple<double, double>(eastingCore, northingCore);
985  }
986 
987 
988  boost::tuple<double, double, double>
989  EventGenerator::GenerateArrayCentricListedCore()
990  {
991  const double newNorthingCore = fCorePositionsIt->get<0>();
992  const double newEastingCore = fCorePositionsIt->get<1>();
993  const double newAltCore = fCorePositionsIt->get<2>();
994  fZone = fCorePositionsIt->get<3>();
995  fBand = fCorePositionsIt->get<4>();
996 
997  ++fCorePositionsIt;
998 
999  return boost::tuple<double, double, double>(newEastingCore, newNorthingCore, newAltCore);
1000  }
1001 
1002 
1003  boost::tuple<double, double>
1004  EventGenerator::GenerateEyeCentricCore(const double energy)
1005  {
1006  const fdet::FDetector& fDetector =
1007  det::Detector::GetInstance().GetFDetector();
1008 
1009  const fdet::Eye& eye = fDetector.GetEye(fEyeid);
1010 
1012 
1013  const double dPhiOneTel = 30*deg;
1014  const double phiMean = 0.5*dPhiOneTel + (fTelid-1) * dPhiOneTel;
1015  const double phiMax = phiMean + 0.5*fDeltaPhi;
1016  const double phiMin = phiMean - 0.5*fDeltaPhi;
1017 
1018  const auto re = &fRandomEngine->GetEngine();
1019  const double phi = RandFlat::shoot(re, phiMin, phiMax);
1020 
1021  const double logEnergy = log10(energy / eV);
1022  const double rmin = fMinDist;
1023  const double rmax = fGeometryCheckCherenkovHECO ?
1024  RcutoffCherenkovHECO(logEnergy) :
1025  (fRMaxEnergyDependent ? Rcutoff(logEnergy) : fMaxDist);
1026 
1027  // Uniform in Area
1028  const double r =
1029  rmin + (rmax - rmin) * sqrt(RandFlat::shoot(re, 0, 1));
1030 
1031  const Point core(r*cos(phi), r*sin(phi), 0, eyeCS);
1032 
1033  const ReferenceEllipsoid& e = ReferenceEllipsoid::GetWGS84();
1034 
1035  const UTMPoint coreUTM(core, e);
1036 
1037  const double newEastingCore = coreUTM.GetEasting();
1038  const double newNorthingCore = coreUTM.GetNorthing();
1039 
1040  fZone = coreUTM.GetZone();
1041  fBand = coreUTM.GetBand();
1042 
1043  return boost::tuple<double, double>(newEastingCore, newNorthingCore);
1044  }
1045 
1046 
1047  boost::tuple<double, double, double>
1048  EventGenerator::GenerateSphereCentricCore(evt::ShowerSimData& shower)
1049  {
1050  fUpgoingShower = false;
1051  const ReferenceEllipsoid& e = ReferenceEllipsoid::GetWGS84();
1052 
1053  const UTMPoint centerUTM(fSphereCenter.get<0>(), fSphereCenter.get<1>(), fSphereCenter.get<2>(),
1054  fSphereCenter.get<3>(), fSphereCenter.get<4>(), e);
1055 
1056  const double azimuth = shower.GetGroundParticleCoordinateSystemAzimuth();
1057  const double zenith = shower.GetGroundParticleCoordinateSystemZenith();
1058 
1059  const CoordinateSystemPtr centerCS = AugerCoordinateSystem::Create(centerUTM.GetPoint(), e, e.GetECEF());
1060 
1061  const auto re = &fRandomEngine->GetEngine();
1062  const double phi = RandFlat::shoot(re, 0, 360*deg);
1063 
1064  const double rmin = 0;
1065  const double rmax = fSphereRadius;
1066 
1067  // Uniform in Area
1068  const double r =
1069  rmin + (rmax - rmin) * sqrt(RandFlat::shoot(re, 0, 1));
1070 
1071  const Vector up(0,0,1, centerCS);
1072  // shower axis pointing up for downgoing showers
1073  const Vector direction(sin(zenith)*cos(azimuth), sin(zenith)*sin(azimuth), cos(zenith), centerCS);
1074 
1075  const Transformation rot = Transformation::Rotation(phi, direction, centerCS);
1076  Vector perpDir = Cross(direction, up);
1077  // to be sure there is no trouble for vertical shower
1078  if (perpDir.GetMag() > 1e-3) {
1079  perpDir = Normalized(rot * perpDir);
1080  } else {
1081  const Vector right(1,0,0, centerCS);
1082  perpDir = Normalized(rot * Cross(direction, right));
1083  }
1084 
1085  const Point impactPoint = centerUTM.GetPoint() + r*perpDir;
1086 
1087  const utl::CoordinateSystemPtr referenceCS = det::Detector::GetInstance().GetReferenceCoordinateSystem();
1088  const Point groundPoint = Point(0,0,0, referenceCS);
1089  const double groundAltitude = UTMPoint(groundPoint, e).GetHeight();
1090 
1091  Point core = impactPoint;
1092 
1093  const vector<Point> pEarth =
1094  Intersection(ReferenceEllipsoid::Get(ReferenceEllipsoid::eWGS84), groundAltitude, Line(impactPoint, direction));
1095  // if there is an intersection between the ground and the shower axis, set the core
1096  if (pEarth.size() == 2) {
1097  // the Earth leaving point = [0], the hitting point = [1] (wrt. the direction vector)
1098  // and the direction is pointing up for downgoing
1099  if (zenith > 90*deg) {
1100  core = pEarth[1];
1101  fUpgoingShower = true;
1102  } else {
1103  core = pEarth[0];
1104  }
1105  }
1106 
1107  const UTMPoint coreUTM(core, e);
1108 
1109  const double newEastingCore = coreUTM.GetEasting();
1110  const double newNorthingCore = coreUTM.GetNorthing();
1111  const double newHeightCore = coreUTM.GetHeight();
1112 
1113  fZone = coreUTM.GetZone();
1114  fBand = coreUTM.GetBand();
1115 
1116  // the azimuth and zenith have to be re-aligned to match the definition in local core CS
1117  // because we want to keep the direction defined by former azimuth/zenith values in local sphere center CS
1118 
1119  const CoordinateSystemPtr coreCS = AugerCoordinateSystem::Create(coreUTM.GetPoint(), e, e.GetECEF());
1120  shower.SetGroundParticleCoordinateSystemAzimuth(direction.GetPhi(coreCS));
1121  shower.SetGroundParticleCoordinateSystemZenith(direction.GetTheta(coreCS));
1122 
1123  // check if the shower is too distant
1124  if (fLimitRp) {
1125  const fdet::FDetector& fDetector = det::Detector::GetInstance().GetFDetector();
1126  fRpTooLarge = true;
1127  for (fdet::FDetector::EyeIterator iEye = fDetector.EyesBegin(); iEye != fDetector.EyesEnd(); ++iEye) {
1128  const Point& eyePos = iEye->GetPosition();
1129  const Vector coreToEye = eyePos - core;
1130  const double rp = (coreToEye - (coreToEye*direction)*direction).GetMag();
1131  const double rpMax = MaximumRp(log10(shower.GetEnergy() / eV));
1132  if (rp < rpMax) {
1133  fRpTooLarge = false;
1134  break;
1135  }
1136  }
1137  }
1138 
1139  return boost::tuple<double, double, double>(newEastingCore, newNorthingCore, newHeightCore);
1140  }
1141 
1142 
1159  double
1160  EventGenerator::Rcutoff(const double lgE)
1161  {
1162  const double x = max(16.5, min(21., lgE));
1163 
1164  const double p1 = 4.86267e+05;
1165  const double p2 = -6.72442e+04;
1166  const double p3 = 2.31169e+03;
1167 
1168  return (p1 + x*(p2 + x*p3)) * meter;
1169  }
1170 
1171 
1172  double
1173  EventGenerator::RcutoffCherenkovHECO(const double lgE)
1174  {
1175  ostringstream info;
1176  if (!fMaxVA) {
1177  info << "fMaxVA not specified, return Rcutoff" << endl;
1178  INFO(info);
1179  return Rcutoff(lgE);
1180  }
1181  const int binLogE = fMaxVA->ProjectionX()->FindBin(lgE);
1182  const double hecoDistance = 169.46*meter;
1183  double maxDist = fMaxVA->ProjectionY()->GetBinLowEdge(fMaxVA->GetNbinsY()+1)*meter + hecoDistance;
1184  if (binLogE < 1 || binLogE > fMaxVA->GetNbinsX()) {
1185  info << "fMaxVA bin not found, maximum distance returned (" << maxDist/meter << ')' << endl;
1186  INFO(info);
1187  return maxDist;
1188  }
1189  for (int i = 1, n = fMaxVA->GetNbinsY()+1; i < n; ++i) {
1190  if (!fMaxVA->GetBinContent(binLogE, i)) {
1191  maxDist = fMaxVA->ProjectionY()->GetBinLowEdge(i)*meter + hecoDistance;
1192  break;
1193  }
1194  }
1195  info << "maximum distance = " << maxDist/meter << endl;
1196  INFO(info);
1197  return maxDist;
1198  }
1199 
1200 
1201  double
1202  EventGenerator::MaximumRp(const double lgEeV)
1203  {
1204  const double x = max(lgEeV, 17.2);
1205  const double p[3] = { 4.68168e-3, 0.5, -19.1270 };
1206  const double q[2] = { 4.0, -26.8000 };
1207  double rpMax = p[0] * exp(p[1]*x) + p[2];
1208  if (x > 19.2) {
1209  rpMax = q[0]*x + q[1];
1210  }
1211  return rpMax * kilometer;
1212  }
1213 
1214 
1215  // Flag any stations that reside within the region
1216  // where no particles are tracked (in case case of Aires)
1217  // or which reside inside limit for radial unthinning
1218  // (in case of Corsika)
1219 
1220  void
1221  EventGenerator::FlagHoleStations(evt::Event& event)
1222  const
1223  {
1224  evt::ShowerSimData& shower = event.GetSimShower();
1225  if (shower.GetMinRadiusCut() <= 0)
1226  shower.SetMinRadiusCut(1*meter);
1227  sevt::SEvent& sEvent = event.GetSEvent();
1228 
1229  const double r = shower.GetMinRadiusCut();
1230  // axes of ellipse formed by shower hole on the ground
1231  const CoordinateSystemPtr& localCS = shower.GetLocalCoordinateSystem();
1232  const double cosZenith = (-shower.GetDirection()).GetCosTheta(localCS);
1233  const double a2 = Sqr(r / cosZenith);
1234  const double b2 = Sqr(r);
1235 
1236  const CoordinateSystemPtr ellipseCS =
1237  CoordinateSystem::RotationZ(
1238  (-shower.GetDirection()).GetPhi(localCS),
1239  localCS
1240  );
1241 
1242  const sdet::SDetector& sDet = det::Detector::GetInstance().GetSDetector();
1243 
1244  for (sdet::SDetector::StationIterator sIt = sDet.StationsBegin();
1245  sIt != sDet.StationsEnd(); ++sIt) {
1246 
1247  const Point& tankPos = sIt->GetPosition();
1248  const int tankId = sIt->GetId();
1249 
1250  const double ellipseBound = Sqr(tankPos.GetX(ellipseCS)) / a2 +
1251  Sqr(tankPos.GetY(ellipseCS)) / b2;
1252 
1253  // Add any stations in the shower hole to the event,
1254  // but flag them as such
1255  if (ellipseBound <= 1) {
1256  if (!sEvent.HasStation(tankId))
1257  sEvent.MakeStation(tankId);
1258  if (!sEvent.GetStation(tankId).HasSimData()) {
1259  sEvent.GetStation(tankId).MakeSimData();
1260  sEvent.GetStation(tankId).GetSimData().SetSimulatorSignature("EventGeneratorOG");
1261  }
1262  sEvent.GetStation(sIt->GetId()).GetSimData().SetIsInsideMinRadius();
1263  }
1264 
1265  }
1266  }
1267 
1268 
1269  utl::Vector
1270  EventGenerator::GetCoreShiftForRadioSimulation(evt::RadioSimulation& radioSim)
1271  {
1272  // probe for an overall position offset between simulations and AERA
1273  // stations and move the core position of the simulation accordingly
1274  const utl::CoordinateSystemPtr& coreSys = radioSim.GetLocalCoordinateSystem();
1275  const rdet::RDetector& radioDet = det::Detector::GetInstance().GetRDetector();
1276  ostringstream odebug;
1277  bool ok = false;
1278  utl::Vector averageOffset;
1279  long numpulses = 0;
1280  long triedPulses = 0;
1281  do {
1282  const evt::SimRadioPulse& srpulse = radioSim.GetNextSimRadioPulse(ok);
1283 
1284  // leave the loop if there were no further SimRadioPulses
1285  if (!ok)
1286  break;
1287 
1288  // check if there is a station in the close vicinity of the SimRadioPulse
1289  const utl::Point& loc = srpulse.GetLocation();
1290  odebug << "\n\tFor pulse: (" << loc.GetX(coreSys) << ", " << loc.GetY(coreSys) << ", " << loc.GetZ(coreSys) << ")";
1291  // for determination of offsets, allow 5 times the nominal allowed maximum distance
1292  const int statID = FindClosestStationFromPoint(loc, radioDet, 5.);
1293 
1294  // if there was no station corresponding to the current SimRadioPulse, go to next SimRadioPulse
1295  ++triedPulses;
1296  if (statID == -1) {
1297  odebug << ", no station could be associated.";
1298  continue;
1299  } else {
1300  odebug << ", closest station id is " << statID;
1301  }
1302 
1303  // if a station was found, register the offset and count the station
1304  averageOffset += (radioDet.GetStation(statID).GetPosition() - loc);
1305  ++numpulses;
1306  } while (true);
1307 
1308  // if many pulses could not be associated print msg.
1309  if (numpulses * 2 < triedPulses)
1310  INFO(odebug);
1311 
1312  // calculate averageOffset
1313  if (!numpulses) {
1314  ostringstream info;
1315  info << "Could not successfully associate any stations out of the " << triedPulses
1316  << " stations in the event. Will now continue with the next event.";
1317  WARNING(info);
1318  return utl::Vector(0, 0, 0, coreSys);
1319  }
1320 
1321  averageOffset *= 1. / numpulses;
1322  return averageOffset;
1323  }
1324 
1325 
1326  int
1327  EventGenerator::FindClosestStationFromPoint(const utl::Point& pt, const rdet::RDetector& rDet, const double maxDistanceFactor)
1328  {
1329  double foundmindist = fMaximumDistance * maxDistanceFactor;
1330  int stid = -1;
1331  for (rdet::RDetector::StationIterator rdIt = rDet.StationsBegin(); rdIt != rDet.StationsEnd(); ++rdIt) {
1332  const double dist = (rdIt->GetPosition() - pt).GetMag();
1333  if (dist < foundmindist) {
1334  stid = rdIt->GetId(); // make current station the closest one
1335  foundmindist = dist;
1336  }
1337  }
1338  return stid;
1339  }
1340 
1341 }
Branch GetTopBranch() const
Definition: Branch.cc:63
boost::transform_iterator< InternalStationFunctor, InternalStationIterator, const Station & > StationIterator
StationIterator returns a pointer to a station.
Definition: RDetector.h:61
AxialVector Cross(const Vector &l, const Vector &r)
Definition: OperationsAV.h:25
utl::CoordinateSystemPtr GetLocalCoordinateSystem() const
Get the Auger coordinate system associated to the shower core position.
const double eV
Definition: GalacticUnits.h:35
void SetCorePosition(const utl::Point &core)
Set the core position of the RadioSimulation using an utl::Point.
const StationIdCollection & GetCrown(const int level) const
Returns a list of station id&#39;s in the crown. If the argument is 0, it returns the station id...
void Normalize()
Definition: Vector.h:64
constexpr T Sqr(const T &x)
Point object.
Definition: Point.h:32
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
bool HasMEvent() const
Detector description interface for Station-related data.
void SetId(const int id)
Definition: MEvent/Header.h:28
double GetMinRadiusCut() const
Get the minimum radius from shower axis for which there are valid particles in the shower...
void MakeSimData()
Make station simulated data object.
Base class for all exceptions used in the auger offline code.
bool HasFEvent() const
void SetTime(const utl::TimeStamp &t)
Definition: Event/Header.h:38
Interface class to access to the SD part of an event.
Definition: SEvent.h:39
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
Definition: BasicVector.h:248
Class to hold and convert a point in geodetic coordinates.
Definition: UTMPoint.h:40
StationIterator StationsEnd() const
End of the collection of pointers to commissioned stations.
Definition: RDetector.h:68
CoordinateSystemPtr GetCoordinateSystem() const
Get the coordinate system of the current internal representation.
Definition: BasicVector.h:234
Data structure for simulated Radio pulses.
Definition: SimRadioPulse.h:29
void SetTime(const utl::TimeStamp &time)
Definition: SEvent/Header.h:22
StationIterator StationsBegin() const
Beginning of the collection of pointers to commissioned stations.
Definition: RDetector.h:64
bool HasSimShower() const
Data structure for a radio simulation (including several SimRadioPulses)
int GetZone() const
Get the zone.
Definition: UTMPoint.h:215
const double meter
Definition: GalacticUnits.h:29
void SetGroundParticleCoordinateSystemAzimuth(const double azimuth)
Set the azimuth angle of the shower. Angle in x-y plane wrt. to the x axis (0 is from east)...
#define INFO(message)
Macro for logging informational messages.
Definition: ErrorLogger.h:161
bool HasRadioSimulation() const
Check initialization of the RadioSimulation.
char GetBand() const
Get the band.
Definition: UTMPoint.h:218
const utl::Point & GetSimCore(const int i) const
utl::Point GetLocation() const
Definition: SimRadioPulse.h:51
void Init()
Initialise the registry.
const Eye & GetEye(const unsigned int eyeId) const
Find eye by numerical Id.
Definition: FDetector.cc:68
Header file holding the SD Event Trigger class definition.
Definition: SEvent/Header.h:16
EyeIterator EyesBegin(const FDetComponentSelector::Type type=FDetComponentSelector::ePhysical) const
iterator pointing to first eye of given type (ePhysical, eVirtual, eAll)
Definition: FDetector.h:72
Detector description interface for Eye-related data.
Definition: FDetector/Eye.h:45
bool ok(bool okay)
Definition: testlib.cc:89
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
double GetNorthing() const
Get the northing.
Definition: UTMPoint.h:206
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.
Detector description interface for FDetector-related data.
Definition: FDetector.h:44
A TimeStamp holds GPS second and nanosecond for some event.
Definition: TimeStamp.h:110
Line Intersection(const Plane &p1, const Plane &p2)
Detector description interface for RDetector-related data.
Definition: RDetector.h:46
utl::Point GetPosition() const
Tank position.
constexpr double deg
Definition: AugerUnits.h:140
void SetId(const std::string &id)
Set the event identifier.
Definition: Event/Header.h:36
Interface class to access Shower Simulated parameters.
Definition: ShowerSimData.h:49
T Get() const
Definition: Branch.h:271
const char * Plural(const T n)
Definition: String.h:104
int GetNSimCores() const
Branch GetNextSibling() const
Get next sibling of this branch.
Definition: Branch.cc:284
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
int GetShowerNumber() const
Get the number of the shower in the file.
Definition: ShowerSimData.h:72
#define max(a, b)
Class representing a document branch.
Definition: Branch.h:107
boost::tuple< double, double, double > Triple
Coordinate triple for easy getting or setting of coordinates.
Definition: Triple.h:15
constexpr double s
Definition: AugerUnits.h:163
void SetTime(const utl::TimeStamp &time)
Definition: FEvent/Header.h:29
Reference ellipsoids for UTM transformations.
boost::filter_iterator< FDetComponentSelector, AllEyeIterator > EyeIterator
Definition: FDetector.h:69
bool HasSimData() const
Check whether station simulated data exists.
const utl::Vector & GetDirection() const
Get the direction of the shower axis. This is the true direction of shower movement.
double GetHeight() const
Get the height.
Definition: UTMPoint.h:212
double GetX(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:206
std::vector< int > StationIdCollection
utl::CoordinateSystemPtr GetEyeCoordinateSystem() const
Returns the Eye Coordinate system.
sdet::Station::StationIdCollection GetInfillCrown(const sdet::Station &centralStation)
constexpr double kPi
Definition: MathConstants.h:24
RadioSimulation & GetRadioSimulation()
Get the radio simulation data.
utl::CoordinateSystemPtr GetLocalCoordinateSystem() const
get local coordinate system anchored at the core position
const Data result[]
Active transformations of geometrical objects.
const utl::Point & GetPosition() const
Get the position of the shower core.
double GetEasting() const
Get the easting.
Definition: UTMPoint.h:209
const double km
double GetEnergy() const
Get the energy of the shower primary particle.
Definition: ShowerSimData.h:89
void MakeStation(const int stationId)
make a station with specifying Id, throw if invalid stationId
Definition: SEvent.cc:65
const CoordinateSystemPtr GetECEF() const
Get the ECEF.
#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
const string file
AxialVector Normalized(const AxialVector &v)
Definition: AxialVector.h:81
Station & GetStation(const int stationId)
retrieve station by id throw utl::NonExistentComponentException if n.a.
Definition: SEvent.h:116
const SimRadioPulse & GetNextSimRadioPulse(bool &ok)
const utl::TimeStamp & GetEventTime() const
Get the event time of the RadioSimulation.
double GetY(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:209
A TimeInterval is used to represent time elapsed between two events.
Definition: TimeInterval.h:43
ResultFlag
Flag returned by module methods to the RunController.
Definition: VModule.h:60
size_t MyPow10(const size_t a)
void SetGroundParticleCoordinateSystemZenith(const double zenith)
Set the zenith angle of the shower. Room angle between z-axis and direction from where the shower is ...
void SetId(const int id)
Definition: SEvent/Header.h:23
std::string GetShowerRunId() const
Get the run id for the shower.
Definition: ShowerSimData.h:78
void MakeGeometry(const utl::Point &pointOnShowerAxis)
initialize the shower geometry. Pos is a point on the shower axis, but not necessarily the core ...
Header information for muon events.
Definition: MEvent/Header.h:20
constexpr double kilometer
Definition: AugerUnits.h:93
void SetMinRadiusCut(const double minR)
Set the minimum radius cut.
Vector object.
Definition: Vector.h:30
void MakeSimShower(const evt::VShowerGeometryProducer &p)
Detector description interface for SDetector-related data.
Definition: SDetector.h:42
void SetId(const int id)
Definition: FEvent/Header.h:27
bool HasTimeStamp() const
Check initialization of the TimeStamp.
void MakeTimeStamp(const utl::TimeStamp &ts)
Make the TimeStamp of the shower.
sevt::StationSimData & GetSimData()
Get simulated data at station level.
AxialVector object.
Definition: AxialVector.h:30
utl::CoordinateSystemPtr Get(const std::string &id)
Get a well-known Coordinate System.
Branch GetFirstChild() const
Get first child of this Branch.
Definition: Branch.cc:98
double GetGroundParticleCoordinateSystemZenith() const
Get the zenith angle of the shower. Room angle between z-axis and direction from where the shower is ...
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:212
const Station & GetStation(const int stationId) const
Get station by Station Id.
Definition: SDetector.cc:192
utl::Point GetPosition() const
Tank position in Site Cartesian Coordinates.
void SetTime(const utl::TimeStamp &time)
Definition: MEvent/Header.h:26
int GetId() const
Station ID.
Point GetPoint(const CoordinateSystemPtr &theCS=CoordinateSystemPtr()) const
Get a cartesian point from an UTMPoint.
Definition: UTMPoint.cc:45
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
constexpr double m
Definition: AugerUnits.h:121
const Station & GetStation(const int stationId) const
Get station by Station Id.
Definition: RDetector.cc:141
double GetGroundParticleCoordinateSystemAzimuth() const
Get the azimuth angle of the shower. Angle in x-y plane wrt. to the x axis (0 is from east)...
Header for an fevt::FEvent.
Definition: FEvent/Header.h:16
bool HasSEvent() const
Definition: Line.h:17
Global event header.
Definition: Event/Header.h:27
EyeIterator EyesEnd(const FDetComponentSelector::Type type=FDetComponentSelector::ePhysical) const
iterator pointing to end of available eyes of given type (ePhysical, eVirtual, eAll) ...
Definition: FDetector.h:76

, generated on Tue Sep 26 2023.