4 #include <fwk/CentralConfig.h>
5 #include <fwk/LocalCoordinateSystem.h>
6 #include <fwk/CoordinateSystemRegistry.h>
7 #include <fwk/MagneticFieldModel.h>
8 #include <fwk/RandomEngineRegistry.h>
11 #include <atm/ProfileResult.h>
12 #include <atm/InclinedAtmosphericProfile.h>
14 #include <det/Detector.h>
15 #include <rdet/RDetector.h>
17 #include <sdet/SDetector.h>
18 #include <sdet/SDetectorConstants.h>
20 #include <evt/Event.h>
21 #include <evt/ShowerRecData.h>
22 #include <evt/ShowerSRecData.h>
23 #include <evt/ShowerRRecData.h>
24 #include <evt/Header.h>
26 #include <revt/REvent.h>
27 #include <revt/Header.h>
29 #include <utl/AugerCoordinateSystem.h>
30 #include <utl/UTMPoint.h>
31 #include <utl/ReferenceEllipsoid.h>
32 #include <utl/AugerUnits.h>
33 #include <utl/Reader.h>
34 #include <utl/UTCDateTime.h>
35 #include <utl/RadioGeometryUtilities.h>
36 #include <utl/RandomEngine.h>
38 #include <CLHEP/Random/RandFlat.h>
41 #include <boost/algorithm/string.hpp>
42 #include <boost/tokenizer.hpp>
57 using CLHEP::RandFlat;
65 Branch topBranch = CentralConfig::GetInstance()->
GetTopBranch(
"RdREASSimPreparatorNG");
68 std::string tmpType = topBranch.
GetChild(
"TypeOfCreatedSimulations").
Get<
string>();
70 if (tmpType ==
"event") {
71 fTypeOfCreatedSimulations = event;
77 }
else if (tmpType ==
"random") {
78 fTypeOfCreatedSimulations = random;
80 Branch branch = topBranch.
GetChild(
"GenerateRandomCardsWithoutEventParameter");
89 }
else if (tmpType ==
"discrete") {
90 fTypeOfCreatedSimulations = discrete;
92 Branch branch = topBranch.
GetChild(
"GenerateDiscreteCardsWithoutEventParameter");
94 branch.
GetChild(
"varyCoreWithinDiscreteADbin").
GetData(fVaryCoreWithinDiscreteADbin);
95 fDiscreteZenithAngles = branch.
GetChild(
"discreteZenithAngles").
Get<vector<double>>();
96 fDiscreteAzimuthAngles = branch.
GetChild(
"discreteAzimuthAngles").
Get<vector<double>>();
97 fDiscreteEnergies = branch.
GetChild(
"discreteEnergies").
Get<vector<double>>();
100 topBranch.
GetChild(
"SimulateInfillEvent").
GetData(fSimulateInfillEvent);
103 topBranch.
GetChild(
"HighEnergyHadronicModel").
GetData(fHighEnergyHadronicModel);
105 topBranch.
GetChild(
"NeutrinoInteractionChannel").
GetData(fNeutrinoInteractionChannel);
106 topBranch.
GetChild(
"TypeOfNeutrinoFirstInt").
GetData(fTypeOfNeutrinoFirstInt);
107 topBranch.
GetChild(
"VariableDepthForNeutrinoChRadius").
GetData(fVariableDepthForNeutrinoChRadius);
108 topBranch.
GetChild(
"NeutrinoFirstIntDepthLow").
GetData(fNeutrinoFirstIntDepthLow);
109 topBranch.
GetChild(
"NeutrinoFirstIntDepthHigh").
GetData(fNeutrinoFirstIntDepthHigh);
110 topBranch.
GetChild(
"NeutrinoFirstIntHeight").
GetData(fNeutrinoFirstIntHeight);
112 if (fTypeOfNeutrinoFirstInt ==
"customPoint" &&
113 fNeutrinoFirstIntDepthLow != fNeutrinoFirstIntDepthHigh) {
114 throw AugerException(
"NeutrinoFirstIntDepthLow must be equal to NeutrinoFirstIntDepthHigh"
115 " in customPoint mode");
137 topBranch.
GetChild(
"WriteAllAERAStations").
GetData(fWriteAllAERAStations);
138 fUseCoreDist = (topBranch.
GetChild(
"DistTo").
Get<
string>() ==
"core");
141 topBranch.
GetChild(
"SlantDepthForCherenkovRadius").
GetData(fSlantDepthForCherenkovRadius);
142 topBranch.
GetChild(
"DistInUnitsOfCherenkovRadii").
GetData(fDistInUnitsOfCherenkovRadii);
146 topBranch.
GetChild(
"MultipleOfCherenkovRadii").
GetData(fMultipleOfCherenkovRadii);
151 if (currentSet.GetName() ==
"OptionSet") {
153 optionSetContainer.
fName = VManager::FindComponent<string>(
"name", currentSet.GetAttributes());
156 if (currentOption.GetName() ==
"option") {
158 opt.
fName = VManager::FindComponent<string>(
"name", currentOption.GetAttributes());
159 opt.
fContent = VManager::FindComponent<string>(
"content", currentOption.GetAttributes());
160 opt.
fComment = VManager::FindComponent<string>(
"comment", currentOption.GetAttributes());
161 optionSetContainer.
fOptions.push_back(opt);
164 fOptionSets.push_back(optionSetContainer);
171 if (currentSet.GetName() ==
"simulation_set") {
173 set.
fNumberOfCards = VManager::FindComponent<int>(
"number_of_cards", currentSet.GetAttributes());
174 set.
fPrimary = VManager::FindComponent<string>(
"primary", currentSet.GetAttributes());
175 fSimulationSets.push_back(set);
179 fRandomEngine = &RandomEngineRegistry::GetInstance().Get(RandomEngineRegistry::eDetector);
186 RdREASSimPreparatorNG::Run(
Event& theEvent)
191 switch(fTypeOfCreatedSimulations)
195 FillEventInput(input, theEvent);
198 fNumberOfSkippedEvents++;
204 fTimeGeneratedEvent = input.
time;
206 for (
const auto& set : fSimulationSets) {
207 const EPrimary primary = ePrimaryConvertor.find(set.fPrimary)->second;
208 const int numberOfCards = set.fNumberOfCards;
209 for (
int cardNumber = 0; cardNumber < numberOfCards; ++cardNumber) {
211 CreateSimulationInput(input);
217 const TimeStamp theTime = fTimeGeneratedEvent;
218 Detector& det = Detector::GetInstance();
223 input.
time = theTime;
225 for (
const auto& set : fSimulationSets) {
226 const EPrimary primary = ePrimaryConvertor.find(set.fPrimary)->second;
227 const int numberOfCards = set.fNumberOfCards;
228 for (
int cardNumber = 0; cardNumber < numberOfCards; ++cardNumber) {
229 FillGenericRandomInput(input);
230 input.
runId = fgsRunNumber;
232 CreateSimulationInput(input);
238 const TimeStamp theTime = fTimeGeneratedEvent;
239 Detector& det = Detector::GetInstance();
244 input.
time = theTime;
246 for (
auto& azimuth : fDiscreteAzimuthAngles)
247 for (
auto& zenith : fDiscreteZenithAngles)
248 for (
auto& energy : fDiscreteEnergies) {
250 utl::Point theCore = GetCore(zenith, azimuth);
252 for (
const auto& set : fSimulationSets) {
253 const EPrimary primary = ePrimaryConvertor.find(set.fPrimary)->second;
254 const int numberOfCards = set.fNumberOfCards;
255 for (
int cardNumber = 0; cardNumber < numberOfCards; ++cardNumber) {
256 if (fVaryCoreWithinDiscreteADbin)
257 theCore = GetCore(zenith, azimuth);
262 input.
runId = fgsRunNumber;
264 input.
axis = theAxis;
265 input.
core = theCore;
268 CreateSimulationInput(input);
284 RdREASSimPreparatorNG::Finish()
287 info <<
"number of skipped events: " << fNumberOfSkippedEvents;
295 RdREASSimPreparatorNG::GetCore(
const double zenith ,
const double azimuth )
301 GenerateCoreForAERA(theCore, zenith, azimuth);
304 GenerateCoreAroundRandomSDStation(theCore);
316 const double azimuth = RandFlat::shoot(&fRandomEngine->GetEngine(),
317 fAzimuthLowGeneratedEvent, fAzimuthHighGeneratedEvent);
320 const double low =
pow(sin(fZenithLowGeneratedEvent), 2);
321 const double high =
pow(sin(fZenithHighGeneratedEvent), 2);
322 const double zenith = asin(
sqrt(RandFlat::shoot(&fRandomEngine->GetEngine(),
low,
high)));
326 if (fEnergyLowGeneratedEvent /
utl::eV == fEnergyHighGeneratedEvent /
utl::eV) {
327 energy = fEnergyLowGeneratedEvent;
329 energy = PowerLaw(fEnergyLowGeneratedEvent /
utl::eV, fEnergyHighGeneratedEvent /
utl::eV,
330 fEnergySlopeGeneratedEvent) *
utl::eV;
333 const utl::Point theCore = GetCore(zenith, azimuth);
338 input.
axis = theAxis;
339 input.
core = theCore;
356 fEventHeader = head.
GetId();
358 std::string eventId = head.
GetId();
359 int rEventId = rHead.
GetId();
363 if (fUseGeometry ==
"SD") {
366 }
else if (fUseGeometry ==
"RD") {
368 throw utl::AugerException(
"no radio core reconstructed, can not generate input cards with radio geometry");
374 throw std::logic_error(
"fUseGeometry has invalid value.");
377 if (fUseEnergy ==
"SD")
379 else if (fUseEnergy ==
"RD")
382 throw std::logic_error(
"fUseEnergy has invalid value.");
385 input.
axis = theAxis;
386 input.
core = theCore;
387 input.
time = theTime;
402 const float energy = input.
energy;
403 const std::string eventId = input.
eventId;
404 const int rEventId = input.
rEventId;
405 const int runId = input.
runId;
412 info <<
"Creating input for SIM" << AddZero(fgsRunNumber, 6) <<
": "
413 <<
"energy = " << energy /
EeV <<
" EeV, zenith = " << theAxis.
GetTheta(coreCS) /
deg
414 <<
" deg, azimuth = " << theAxis.
GetPhi(coreCS) /
deg <<
" deg, primary = " << primary;
417 if (fModelMagField) {
421 fMagFieldX =
sqrt(
Sqr(theMagFieldVector.
GetX(coreCS)) +
Sqr(theMagFieldVector.
GetY(coreCS)));
422 fMagFieldY = -theMagFieldVector.
GetZ(coreCS);
425 const string runNumber = AddZero(fgsRunNumber, 6);
426 string corsikaFileName =
"RUN" + runNumber +
".inp";
427 const string coreasContent = CreateCoREASContent(theCore, theAxis, energy, corsikaFileName,
428 theTime, eventId, rEventId, runId);
430 corsikaFileName = fWorkingDir + corsikaFileName;
431 const string coreasFileName = fWorkingDir +
"SIM" + runNumber +
".reas";
432 const string coreasListFileName = fWorkingDir +
"SIM" + runNumber +
".list";
434 const string corsikaContent = CreateCORSIKAContent(theAxis, energy, theCore, primary);
435 const string coreasListContent = CreateCoREASListContent(theCore, theAxis, primary);
436 RecordFile(corsikaFileName, corsikaContent);
437 RecordFile(coreasFileName, coreasContent);
438 RecordFile(coreasListFileName, coreasListContent);
440 if (HasOptionSet(
"BASH")) {
441 const string bashFileName = fWorkingDir +
"SIM" + runNumber +
".sh";
442 const string bashContent = CreateBashContent(corsikaFileName);
443 RecordFile(bashFileName, bashContent);
452 RdREASSimPreparatorNG::PowerLaw(
const double min,
const double max,
const double index)
457 if (min > 0 && max > 0) {
458 double randNo = RandFlat::shoot(&fRandomEngine->GetEngine(), 0, 1);
460 x =
pow(
pow(min, index + 1) + randNo * (
pow(max, index + 1) -
pow(min, index + 1)),
463 x = min*
pow(max/min, randNo);
466 INFO(
"Impossible to dice!");
473 RdREASSimPreparatorNG::RecordFile(
const std::string&
filename,
474 const std::string& buffer)
482 RdREASSimPreparatorNG::CreateCORSIKAContent(
const utl::Vector& theAxis,
487 const std::vector<Option> optionSet = GetOptionSet(
"CORSIKA");
490 ostringstream buffer;
491 buffer << std::scientific
493 << std::setprecision(8)
499 const float zen = theAxis.
GetTheta(coreCS);
501 std::string thinRadius;
503 thinRadius =
"300.0E+02";
504 INFO(
"You are using photon primaries. You should activate Preshowering"
505 " which is not an input parameter but a CORSIKA compiling option.");
507 thinRadius =
"50.0E+02";
510 if (primary == eElectronNeutrino || primary == eTauNeutrino) {
514 buffer <<
"RUNNR " << AddZero(fgsRunNumber, 6) <<
"\n"
517 if (fSimulatedParallel) {
518 buffer <<
"PARALLEL 1000 "
519 << (energy /
GeV) * fParallelWeight <<
" 1 F\n";
523 for (
int seedCnt = 1; seedCnt <= fSeedAmount; ++seedCnt)
524 buffer <<
"SEED " << (
unsigned int)(RandFlat::shoot(&fRandomEngine->GetEngine(), 0, 1) * 999999)
527 buffer << std::setprecision(6);
528 buffer <<
"PRMPAR " << (
unsigned long)(primary) <<
"\n"
529 "ERANGE " << energy /
GeV <<
" " << energy /
GeV <<
"\n"
530 "THETAP " << zen /
degree <<
" " << zen /
degree <<
"\n"
532 "THIN " << fThinLevel <<
" " << (energy /
GeV * fThinLevel) <<
" " << thinRadius <<
"\n"
534 "DIRECT " << fWorkingDir <<
'\n';
537 buffer <<
"GCOORD -69.5848 -35.4634 2003 1 0\n";
540 if (fHighEnergyHadronicModel ==
"SIBYLL") {
541 buffer <<
"SIBYLL T 0\n"
542 <<
"SIBSIG T cross-section enabled\n";
545 if (fHighEnergyHadronicModel ==
"QGSJETII04") {
546 buffer <<
"QGSJET T 0\n"
550 if (fHighEnergyHadronicModel ==
"EPOS-LHC") {
551 buffer <<
"EPOS T 0\n"
553 <<
"EPOPAR input /path/to/epos.param initialization input file for epos\n"
554 <<
"EPOPAR fname inics /path/to/epos.inics initialization input file for epos\n"
555 <<
"EPOPAR fname iniev /path/to/epos.iniev initialization input file for epos\n"
556 <<
"EPOPAR fname initl /path/to/epos.initl initialization input file for epos\n"
557 <<
"EPOPAR fname inirj /path/to/epos.inirj initialization input file for epos\n"
558 <<
"EPOPAR fname inihy /path/to/epos.ini1b initialization input file for epos\n"
559 <<
"EPOPAR fname check none dummy output file for epos\n"
560 <<
"EPOPAR fname histo none dummy output file for epos\n"
561 <<
"EPOPAR fname data none dummy output file for epos\n"
562 <<
"EPOPAR fname copy none dummy output file for epos\n";
565 if (primary == eElectronNeutrino || primary == eTauNeutrino) {
566 if (fTypeOfNeutrinoFirstInt ==
"randomPoint") {
568 const auto& theAtm = Detector::GetInstance().GetAtmosphere();
569 theAtm.InitSlantProfileModel(core, theAxis, 5 *
g /
cm2);
570 const auto& heightFromSlantDepth = theAtm.EvaluateHeightVsSlantDepth();
572 if (fNeutrinoFirstIntDepthLow == fNeutrinoFirstIntDepthHigh) {
573 fNeutrinoFirstIntDepth = fNeutrinoFirstIntDepthLow;
575 const auto& slantDepthFromDistance = theAtm.EvaluateSlantDepthVsDistance();
576 const double slantDepthAtGround = slantDepthFromDistance.Y(0);
578 double maxDepth = fNeutrinoFirstIntDepthHigh;
579 if (maxDepth/(
g/
cm2) == -1) {
583 maxDepth = slantDepthAtGround - 500*(
g/
cm2);
586 fNeutrinoFirstIntDepth = RandFlat::shoot(&fRandomEngine->GetEngine(), fNeutrinoFirstIntDepthLow, maxDepth);
589 info <<
"choose first interaction randomly in [" << fNeutrinoFirstIntDepthLow / (
g/
cm2) <<
", "
590 << maxDepth / (
g/
cm2) <<
"]: " << fNeutrinoFirstIntDepth / (
g/
cm2) <<
" g/cm2";
594 fixhei = heightFromSlantDepth.Y(fNeutrinoFirstIntDepth);
597 if (fTypeOfNeutrinoFirstInt ==
"customPoint") {
598 fNeutrinoFirstIntDepth = fNeutrinoFirstIntDepthLow;
599 fixhei = fNeutrinoFirstIntHeight;
603 info <<
"\nDepth of first interaction " << fNeutrinoFirstIntDepth / (
g/
cm2) <<
" g/cm2, "
604 <<
"height of first interaction " << fixed << setprecision(0) << fixhei /
cm <<
" cm."
605 << setprecision(6) << scientific;
608 buffer <<
"NUSLCT " << fNeutrinoInteractionChannel
609 <<
" Neutrino interaction channel (0: neutral current, 1: charged current, 2: random)\n"
610 <<
"FIXHEI " << fixed << setprecision(0) << fixhei /
cm << setprecision(6)
611 << scientific <<
" 1 Height of first interaction (cm)\n"
612 <<
"HILOW 200 Transition energy between models" <<
"\n";
615 for (
const auto& opt : optionSet)
616 buffer << opt.fName <<
" " << opt.fContent <<
" " << opt.fComment <<
'\n';
618 buffer <<
"DATBAS " << fCreateDatabase <<
"\n"
619 <<
"USER " << fUserName <<
" user name for database file\n"
620 <<
"HOST " << fHostName <<
" host name for database file\n"
628 RdREASSimPreparatorNG::CreateCoREASContent(
const utl::Point& thecore,
631 const string& corsikaparameterfile,
633 const std::string eventId,
637 const std::vector<Option> optionSet = GetOptionSet(
"CoREAS");
639 ostringstream buffer;
640 buffer << std::scientific
642 << std::setprecision(6)
648 const float zen = theAxis.
GetTheta(coreCS);
650 UTMPoint utmcore(thecore, ReferenceEllipsoid::GetWGS84());
652 buffer <<
"# CoREAS V1 parameter file\n"
655 "# parameters setting up the spatial observer configuration:\n"
657 "CoreCoordinateNorth = 0 ; in cm\n"
658 "CoreCoordinateWest = 0 ; in cm\n"
659 "CoreCoordinateVertical = " << utmcore.
GetHeight() /
cm <<
" ; in cm\n"
662 for (
const auto& opt : optionSet)
663 buffer << opt.fName <<
" = " << opt.fContent <<
" ; " << opt.fComment <<
'\n';
666 "# parameters read from CORSIKA files, these are not interpreted by CoREAS but stated here for your convenience\n"
668 "PrimaryParticleEnergy = " << energy /
eV <<
" ; in eV\n"
669 "ShowerZenithAngle = " << zen /
degree <<
" ; in degrees\n"
670 "ShowerAzimuthAngle = " << az /
degree <<
" ; in degrees, 0: shower propagates to north, 90: to west\n"
672 "# book-keeping parameters needed for read-in to Offline\n"
674 "CorsikaFilePath = " << fWorkingDir <<
"\n"
675 "CorsikaParameterFile = " << corsikaparameterfile <<
" ; specify CORSIKA card file\n"
676 "EventNumber = " << (
unsigned long)(rEventId) <<
"\n"
677 "RunNumber = " << (
unsigned long)(runId) <<
"\n"
680 "GPSNanoSecs = " << (
unsigned long)(theTime.
GetGPSNanoSecond() + 0.5) <<
"\n"
681 "CoreEastingOffline = " << thecore.
GetX(PampaAmarillaCS) /
meter <<
" ; in meters\n"
682 "CoreNorthingOffline = " << thecore.
GetY(PampaAmarillaCS) /
meter <<
" ; in meters\n"
683 "CoreVerticalOffline = " << thecore.
GetZ(PampaAmarillaCS) /
meter <<
" ; in meters\n"
684 "RotationAngleForMagfieldDeclination = " << fMagFieldDec /
degree <<
" ; in degrees\n"
685 "Comment = Event " << GetEventNumber(eventId)
687 <<
" ; created by RdREASSimPreparator, Offline coordinates are in PampaAmarilla coordinate system\n";
694 RdREASSimPreparatorNG::GetEarlyLateCorrectedAxisDistance(
const Point& core,
const Vector& axis,
695 const Point& position,
const double distanceToApex)
709 const double cEarlyLate =
717 RdREASSimPreparatorNG::IsStationToFarAway(
const Point& core,
const Vector& axis,
718 const Point& position,
const double maxRadius,
719 const double distanceToApex)
723 const Vector vecAntenna = position - core;
730 axisDist = GetEarlyLateCorrectedAxisDistance(core, axis, position, distanceToApex);
732 axisDist = RadioGeometryUtilities::GetDistanceToAxis(axis, core, position);
734 if (axisDist > maxRadius)
743 RdREASSimPreparatorNG::CreateCoREASListContent(
const Point& core,
const Vector& axis,
const EPrimary primary)
746 const UTMPoint utmcore(core, ReferenceEllipsoid::GetWGS84());
747 const Detector& det = Detector::GetInstance();
749 vector<Point> antennaPositions;
750 vector<string> antennaNames;
752 double maxRadius = 0;
753 double distanceToApex = 0;
754 if (fDistInUnitsOfCherenkovRadii) {
757 double usedDepth = fSlantDepthForCherenkovRadius;
758 if ((primary == eElectronNeutrino || primary == eTauNeutrino) && fVariableDepthForNeutrinoChRadius) {
759 info <<
"\nDepth of first interaction at " << fNeutrinoFirstIntDepth / (
g/
cm2) <<
" g/cm2.";
760 usedDepth += fNeutrinoFirstIntDepth;
763 info <<
"\nCalculating Cherenkov radius at " << usedDepth / (
g/
cm2) <<
" g/cm2. " << endl;
766 auto radiusAndDistance = CherenkovRadius(core, axis, usedDepth);
767 maxRadius =
std::max(fCherenkovRadii * radiusAndDistance.first, fMinMaxAntDist);
768 distanceToApex = radiusAndDistance.second;
770 maxRadius = fMaxAntDist;
773 if (fWriteAERAlist) {
775 for (
const auto& rdStation : radioDet.StationsRange()) {
776 if (!rdStation.IsInGrid())
779 const Point& position = rdStation.GetPosition();
781 if (!fWriteAllAERAStations && IsStationToFarAway(core, axis, position, maxRadius, distanceToApex))
784 antennaNames.push_back(rdStation.GetName());
785 antennaPositions.push_back(rdStation.GetPosition());
798 const Point& position = station.GetPosition();
800 if (IsStationToFarAway(core, axis, position, maxRadius, distanceToApex))
803 antennaNames.push_back(std::to_string(station.GetId()));
804 antennaPositions.push_back(station.GetPosition());
808 ostringstream buffer;
809 buffer << std::scientific
811 << std::setprecision(6)
814 for (
unsigned int i = 0, n = antennaPositions.size(); i < n; ++i) {
815 const double antX = antennaPositions[i].
GetX(coreCS);
816 const double antY = antennaPositions[i].GetY(coreCS);
817 const double antZ = utmcore.
GetHeight() + antennaPositions[i].GetZ(coreCS);
820 const double rotX = cos(fMagFieldDec) * antX - sin(fMagFieldDec) * antY;
821 const double rotY = sin(fMagFieldDec) * antX + cos(fMagFieldDec) * antY;
824 buffer <<
"AntennaPosition = "
826 << -rotX /
cm <<
'\t'
828 << antennaNames[i] <<
'\n';
836 RdREASSimPreparatorNG::CreateBashContent(
const string& corsikaparameterfile)
838 const std::vector<Option> optionSet = GetOptionSet(
"BASH");
840 ostringstream buffer;
841 buffer << std::scientific
842 << std::setprecision(6)
845 buffer <<
"#!/bin/bash\n";
847 for (
const auto& opt : optionSet)
848 buffer << opt.fName <<
'\n';
850 buffer <<
"cd " << fCorsikapath <<
"\n"
851 "./" << fCorsikaBin <<
" "
852 "<" << corsikaparameterfile <<
" "
853 ">" << fWorkingDir <<
"SIM" << AddZero(fgsRunNumber, 6) <<
".log "
862 RdREASSimPreparatorNG::GetEventNumber(
const std::string& eventId)
864 boost::char_separator<char> sep(
"_");
865 boost::tokenizer<boost::char_separator<char>> tok(eventId, sep);
866 const vector<string> thetokens(tok.begin(), tok.end());
868 if (thetokens.size() >= 4)
876 RdREASSimPreparatorNG::AddZero(
const int runID,
const int numberofdigit)
878 std::string pad =
"%0" + std::to_string(numberofdigit) +
"i";
879 ostringstream runnumb;
880 runnumb << boost::format(pad) % runID;
881 return runnumb.str();
886 RdREASSimPreparatorNG::GetOptionSet(
const string& setName)
889 std::vector<Option> optionSet;
890 for (
const auto& opt : fOptionSets) {
891 if (opt.fName == setName) {
892 optionSet = opt.fOptions;
901 RdREASSimPreparatorNG::HasOptionSet(
const string &setName)
904 bool hasOptionSet =
false;
905 for (
const auto &opt : fOptionSets) {
906 if (opt.fName == setName) {
916 RdREASSimPreparatorNG::GenerateCoreAroundStation(
const utl::Point& center,
const std::vector<utl::Point>& crownStations,
922 double maxSquare = 0;
923 if (fSimulateInfillEvent)
924 maxSquare = 1000 *
meter;
926 maxSquare = 2000 *
meter;
928 double eastingCore, northingCore;
932 RandFlat::shoot(&fRandomEngine->GetEngine(), -0.5, 0.5) * maxSquare;
934 RandFlat::shoot(&fRandomEngine->GetEngine(), -0.5, 0.5) * maxSquare;
941 for (
auto const& stPoint : crownStations) {
942 const Vector crownStationVector = stPoint - center;
943 in = in && (crownStationVector * randomVector < crownStationVector * crownStationVector / 2);
949 theCore = newPosition.GetPoint();
958 const double gridSize = 750;
959 const sdet::SDetector& det = det::Detector::GetInstance().GetSDetector();
960 for (
const auto&
s : det.StationsRange()) {
962 s.GetId() != centralStation.
GetId() &&
963 (
s.GetPosition() - centralStation.
GetPosition()).GetMag() < 1.5 * gridSize)
964 stations.push_back(
s.GetId());
971 RdREASSimPreparatorNG::GenerateCoreAroundRandomSDStation(
utl::Point& theCore)
974 const sdet::SDetector& theDet = det::Detector::GetInstance().GetSDetector();
976 std::vector<int> stationList;
978 for (
const auto& station : theDet.StationsRange()) {
979 if (fSimulateInfillEvent) {
982 stationList.push_back(station.GetId());
987 station.GetCrown(1).size() == 6)
988 stationList.push_back(station.GetId());
992 if (stationList.empty())
993 throw utl::AugerException(
"Asked to simulate around a random station but I get an empty list of stations.");
996 const int stationPos = int(RandFlat::shoot(&fRandomEngine->GetEngine(), 0, 1) * stationList.size()) ;
997 const int stationId = stationList[stationPos];
1002 if (fSimulateInfillEvent)
1007 std::vector<utl::Point> crownStations;
1008 for (
const auto& station : stations)
1012 GenerateCoreAroundStation(center, crownStations, theCore);
1017 RdREASSimPreparatorNG::GenerateCoreForAERA(
utl::Point& theCore,
const double zenith,
const double azimuth)
1027 GenerateCoreAroundRandomSDStation(theCore);
1031 }
while (!EventHitsAERA(theCore, theAxis, fMinNumberOfStation, fMultipleOfCherenkovRadii));
1036 RdREASSimPreparatorNG::GetSeaLevelRefractiveIndex()
1038 const std::vector<Option> optionSet = GetOptionSet(
"CoREAS");
1039 float refractiveIndexSeaLevel = 0;
1040 for (
const auto& opt : optionSet) {
1041 if (opt.fName ==
"GroundLevelRefractiveIndex") {
1042 refractiveIndexSeaLevel = std::stof(opt.fContent);
1046 if (!refractiveIndexSeaLevel)
1050 return refractiveIndexSeaLevel;
1054 std::pair<double, double>
1057 const bool useParamCorrection)
1060 const atm::Atmosphere& theAtm = Detector::GetInstance().GetAtmosphere();
1068 const double distanceToXmax =
abs(distanceFromDepth.
Y(depth));
1069 const double densityAtXmax = densityFromHeight.
Y(heightFromDistance.
Y(-distanceToXmax)) / (
kg /
m3);
1070 const double densityAtSeaLevel = densityFromHeight.
Y(0) / (
kg/
m3);
1071 const float refractiveIndexSeaLevel = GetSeaLevelRefractiveIndex();
1072 const float refractiveIndexAtXmax = 1 + (refractiveIndexSeaLevel - 1) * densityAtXmax / densityAtSeaLevel;
1075 double cherenkovAngle = std::acos(1 / refractiveIndexAtXmax);
1076 if (useParamCorrection) {
1077 const double correctionFactor = 9.48990456e-01 -
1078 std::pow(4.48698860e+03 / distanceToXmax, 1.43097665e+00) - distanceToXmax / 2.46630811e+06;
1079 cherenkovAngle *= correctionFactor;
1082 const double cherenkovRadius = std::tan(cherenkovAngle) * distanceToXmax;
1083 return std::make_pair(cherenkovRadius, distanceToXmax);
1088 RdREASSimPreparatorNG::EventHitsAERA(
const Point& core,
const Vector& axis,
1089 const unsigned int nStation,
const unsigned int nCherenkov)
1096 const auto radiusAndDistance = CherenkovRadius(core, axis, fSlantDepthForCherenkovRadius);
1097 const double cherenkovRadius = radiusAndDistance.first;
1098 const double distanceToApex = radiusAndDistance.second;
1100 unsigned int closeStations = 0;
1102 const rdet::RDetector& radioDet = Detector::GetInstance().GetRDetector();
1103 for (
const auto& rdStation : radioDet.StationsRange()) {
1104 if (!rdStation.IsInGrid())
1107 const Point& position = rdStation.GetPosition();
1108 const double axisDist = GetEarlyLateCorrectedAxisDistance(core, axis, position, distanceToApex);
1110 if (axisDist < nCherenkov * cherenkovRadius)
1114 return closeStations > nStation;
Branch GetTopBranch() const
void Update(const utl::TimeStamp &time, const bool invData=true, const bool invComp=true, const bool forceRadio=false)
Update detector: deletes currently constructed stations and sets new time.
Top of the interface to Atmosphere information.
const StationIdCollection & GetCrown(const int level) const
Returns a list of station id's in the crown. If the argument is 0, it returns the station id...
std::vector< Option > fOptions
utl::Vector GetAxis() const
Returns vector of the shower axis.
constexpr T Sqr(const T &x)
double GetPhi(const CoordinateSystemPtr &coordinateSystem) const
azimuth (phi) angle in spherical and cylindrical coordinates
void InitSlantProfileModel(const utl::Point &core, const utl::Vector &dir, const double deltaX) const
Detector description interface for Station-related data.
static double GetEarlyLateCorrectionFactor(const utl::Point &showerCore, const utl::Point &stationPosition, const utl::Point &showerMax, const utl::Vector &showerAxis)
Base class for all exceptions used in the auger offline code.
evt::Header & GetHeader()
Interface class to access Shower Reconstructed parameters.
Interface class to access to the Radio part of an event.
double GetR(const CoordinateSystemPtr &coordinateSystem) const
radius r in spherical coordinates coordinates (distance to origin)
double GetTheta(const CoordinateSystemPtr &coordinateSystem) const
zenith (theta) angle in spherical coordinates
Class to hold and convert a point in geodetic coordinates.
CoordinateSystemPtr GetCoordinateSystem() const
Get the coordinate system of the current internal representation.
ShowerRecData & GetRecShower()
const atm::ProfileResult & EvaluateDensityVsHeight() const
Tabulated function giving Y=density as a function of X=height.
int GetZone() const
Get the zone.
const atm::ProfileResult & EvaluateDistanceVsSlantDepth() const
Table of distance as a function of slant depth.
bool HasCorePosition() const
Return true if all 3 core parameter are set.
#define INFO(message)
Macro for logging informational messages.
char GetBand() const
Get the band.
static double GetDeclination(const utl::Point &position, const utl::TimeStamp &time)
returns declination in radians
void Init()
Initialise the registry.
revt::REvent & GetREvent()
vector< t2list > out
output of the algorithm: a list of clusters
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
double pow(const double x, const unsigned int i)
double GetNorthing() const
Get the northing.
ShowerRRecData & GetRRecShower()
ShowerSRecData & GetSRecShower()
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.
Detector description interface for RDetector-related data.
utl::Point GetPosition() const
Tank position.
Branch GetNextSibling() const
Get next sibling of this branch.
boost::shared_ptr< const CoordinateTransformer > CoordinateSystemPtr
Shared pointer for coordinate systems.
#define INFOIntermediate(y)
Class representing a document branch.
Reference ellipsoids for UTM transformations.
double GetHeight() const
Get the height.
double GetX(const CoordinateSystemPtr &coordinateSystem) const
std::vector< int > StationIdCollection
Class describing the Atmospheric profile.
sdet::Station::StationIdCollection GetInfillCrown(const sdet::Station ¢ralStation)
static MagneticFieldModel & instance()
double abs(const SVector< n, T > &v)
Header & GetHeader()
access to REvent Header
Structure holding content to be put in the stearing card.
Top of the hierarchy of the detector description interface.
const sdet::SDetector & GetSDetector() const
static utl::Vector GetMagneticFieldVector(const utl::Point &position, const utl::TimeStamp &time)
returns the magnetic field at a specific place at a specific time
double GetEasting() const
Get the easting.
const utl::Vector & GetAxis() const
static const CSpherical kSpherical
void GetData(bool &b) const
Overloads of the GetData member template function.
void GetVectorInShowerPlaneVxB(double &x, double &y, double &z, const utl::Point &point) const
in case of positions, the positions has to be relative to the core positions!!!
double GetY(const CoordinateSystemPtr &coordinateSystem) const
ResultFlag
Flag returned by module methods to the RunController.
unsigned long GetGPSSecond() const
GPS second.
double GetGPSNanoSecond() const
GPS nanosecond.
Detector description interface for SDetector-related data.
const utl::Point & GetCorePosition() const
utl::Point GetCorePosition() const
returns pointer of the position vector of the core in the reference coor system
const rdet::RDetector & GetRDetector() const
utl::CoordinateSystemPtr Get(const std::string &id)
Get a well-known Coordinate System.
double GetParameter(const Parameter i) const
Branch GetFirstChild() const
Get first child of this Branch.
double GetZ(const CoordinateSystemPtr &coordinateSystem) const
const Station & GetStation(const int stationId) const
Get station by Station Id.
std::string GetInXMLFormat() const
static Policy::type Create(const utl::Point &theOrigin)
Create the standard local coordinate system for a Point.
int GetId() const
Station ID.
double NormalizeAngleZero2Pi(const double x)
Normalize angle to lie between 0 and 2pi (0 and 360 deg)
const atm::ProfileResult & EvaluateHeightVsDistance() const
Table of height as a function of distance.
const char * what() const
std::exception will print this on crash