103 using std::ostringstream;
105 using namespace genie;
106 using namespace genie::hnl;
107 using namespace genie::hnl::enums;
109 #ifdef __GENIE_GEOM_DRIVERS_ENABLED__
110 #define __CAN_USE_ROOT_GEOM__
111 #include <TGeoVolume.h>
112 #include <TGeoManager.h>
113 #include <TGeoShape.h>
114 #include <TGeoBBox.h>
115 #endif // #ifdef __GENIE_GEOM_DRIVERS_ENABLED__
128 #ifdef __CAN_USE_ROOT_GEOM__
129 void InitBoundingBox (
void);
130 #endif // #ifdef __CAN_USE_ROOT_GEOM__
162 #ifdef __CAN_USE_ROOT_GEOM__
163 TGeoManager * gOptRootGeoManager = 0;
164 TGeoVolume * gOptRootGeoVolume = 0;
165 #endif // #ifdef __CAN_USE_ROOT_GEOM__
194 int main(
int argc,
char ** argv)
197 gErrorIgnoreLevel = kWarning;
215 const Decayer * hnlgen =
dynamic_cast< const Decayer *
>( algHNLGen );
218 bool geom_is_accessible = ! (gSystem->AccessPathName(
gOptRootGeom.c_str()));
219 if (!geom_is_accessible) {
221 <<
"The specified ROOT geometry doesn't exist! Initialization failed!";
226 if( !gOptRootGeoManager ) gOptRootGeoManager = TGeoManager::Import(
gOptRootGeom.c_str());
228 TGeoVolume * top_volume = gOptRootGeoManager->GetTopVolume();
229 assert( top_volume );
230 __attribute__((unused)) TGeoShape * ts = top_volume->GetShape();
247 while( stIntChannels.size() > 0 ){
250 std::string tmpSt = stIntChannels.substr( stIntChannels.size()-1, stIntChannels.size() );
251 if( std::strcmp( tmpSt.c_str(),
"1" ) == 0 )
254 stIntChannels.erase( stIntChannels.end()-1, stIntChannels.end() );
265 <<
"Initialised Ntuple Writer";
300 <<
"Initialised MC job monitor";
305 #ifdef __CAN_USE_ROOT_GEOM__
310 #endif // #ifdef __CAN_USE_ROOT_GEOM__
318 <<
"\nPlease check ${GENIE}/config/CommonHNL.xml sections \"ParamSpace\" and \"ParticleGun\"";
329 if( ievent % (
gOptNev / 1000 ) == 0 ){
330 int irat = ievent / (
gOptNev / 1000 );
331 std::cerr << 0.1 * irat <<
" % " <<
" ( " << ievent
332 <<
" / " <<
gOptNev <<
" ) \r" << std::flush;
335 if( ievent % (
gOptNev / 10 ) == 0 ){
336 int irat = ievent / (
gOptNev / 10 );
337 std::cerr << 10.0 * irat <<
" % " <<
" ( " << ievent
338 <<
" / " <<
gOptNev <<
" ) \r" << std::flush;
345 <<
" *** Generating event............ " << ievent;
362 <<
"No decay mode specified - sampling from all available modes.";
370 event->AttachSummary(interaction);
378 event->AddParticle( ptHNL );
390 NTP_FS0_E = ((
event->Particle(1))->P4())->E();
391 NTP_FS0_PX = ((
event->Particle(1))->P4())->Px();
392 NTP_FS0_PY = ((
event->Particle(1))->P4())->Py();
393 NTP_FS0_PZ = ((
event->Particle(1))->P4())->Pz();
395 NTP_FS1_E = ((
event->Particle(2))->P4())->E();
396 NTP_FS1_PX = ((
event->Particle(2))->P4())->Px();
397 NTP_FS1_PY = ((
event->Particle(2))->P4())->Py();
398 NTP_FS1_PZ = ((
event->Particle(2))->P4())->Pz();
399 if( event->Particle(3) ){
401 NTP_FS2_E = ((
event->Particle(3))->P4())->E();
402 NTP_FS2_PX = ((
event->Particle(3))->P4())->Px();
403 NTP_FS2_PY = ((
event->Particle(3))->P4())->Py();
404 NTP_FS2_PZ = ((
event->Particle(3))->P4())->Pz();
423 <<
"Generated event: " << *event;
427 mcjmonitor.
Update(ievent,event);
442 #ifdef __CAN_USE_ROOT_GEOM__
443 void InitBoundingBox(
void)
448 <<
"Initialising geometry bounding box.";
459 bool geom_is_accessible = ! (gSystem->AccessPathName(
gOptRootGeom.c_str()));
460 if (!geom_is_accessible) {
462 <<
"The specified ROOT geometry doesn't exist! Initialization failed!";
466 if( !gOptRootGeoManager ) gOptRootGeoManager = TGeoManager::Import(
gOptRootGeom.c_str());
468 TGeoVolume * top_volume = gOptRootGeoManager->GetTopVolume();
469 assert( top_volume );
470 TGeoShape * ts = top_volume->GetShape();
472 TGeoBBox * box = (TGeoBBox *)ts;
482 fox = (box->GetOrigin())[0];
483 foy = (box->GetOrigin())[1];
484 foz = (box->GetOrigin())[2];
487 <<
"Before conversion the bounding box has:"
488 <<
"\nOrigin = ( " <<
fox <<
" , " <<
foy <<
" , " <<
foz <<
" )"
489 <<
"\nDimensions = " <<
fdx <<
" x " <<
fdy <<
" x " <<
fdz
490 <<
"\n1cm = 1.0 unit";
501 <<
"Initialised bounding box successfully.";
504 #endif // #ifdef __CAN_USE_ROOT_GEOM__
511 double pMag = std::sqrt( E*E - M*M );
514 const Decayer * hnlgen =
dynamic_cast< const Decayer *
>( algHNLGen );
523 double cx = PGDirection.at(0), cy = PGDirection.at(1), cz = PGDirection.at(2);
524 double c2 = std::sqrt( cx*cx + cy*cy + cz*cz );
527 cx *= 1.0 / c2; cy *= 1.0 / c2; cz *= 1.0 / c2;
529 double theta = TMath::ACos( cz / c2 );
530 double phi = ( TMath::Sin( theta ) != 0.0 ) ? TMath::ACos( cx / ( c2 * TMath::Sin( theta ) ) ) : 0.0;
538 double dthetaDeg = PGunDeviation.at(0), dphiDeg = PGunDeviation.at(1);
543 double dTheta = rng->
RndGen().Uniform( -dThetaMax, dThetaMax );
544 double dPhi = rng->
RndGen().Uniform( -dPhiMax, dPhiMax );
546 std::ostringstream asts;
548 <<
"Output details for the momentum:"
549 <<
"\nDirectional cosines: ( " << cx <<
", " << cy <<
", " << cz <<
" )"
551 <<
", " << phi * 180.0 /
constants::kPi <<
" ) [deg] on unit sphere"
552 <<
"\nApplied deviation: dTheta = " << dTheta * 180.0 /
constants::kPi
556 theta += dTheta; phi += dPhi;
557 TLorentzVector * p4HNL =
new TLorentzVector();
558 p4HNL->SetPxPyPzE( pMag * TMath::Sin( theta ) * TMath::Cos( phi ),
559 pMag * TMath::Sin( theta ) * TMath::Sin( phi ),
560 pMag * TMath::Cos( theta ), E );
567 LOG(
"gevgen_pghnl",
pDEBUG ) << asts.str();
576 const Decayer * hnlgen =
dynamic_cast< const Decayer *
>( algHNLGen );
585 double ox = PGOrigin.at(0), oy = PGOrigin.at(1), oz = PGOrigin.at(2);
594 double Dxmax = PGDOrigin.at(0), Dymax = PGDOrigin.at(1), Dzmax = PGDOrigin.at(2);
597 double dx = rng->
RndGen().Uniform( -Dxmax, Dxmax );
598 double dy = rng->
RndGen().Uniform( -Dymax, Dymax );
599 double dz = rng->
RndGen().Uniform( -Dzmax, Dzmax );
602 ox += dx; oy += dy; oz += dz;
603 TLorentzVector * x4HNL =
new TLorentzVector();
604 x4HNL->SetXYZT( ox, oy, oz, 0.0 );
606 event->SetVertex( *x4HNL );
620 TLorentzVector x4 = *(
event->Vertex());
625 TRandom3 & rnd_geo = rnd->RndGeom();
627 double rndx = 2 * (rnd_geo.Rndm() - 0.5);
628 double rndy = 2 * (rnd_geo.Rndm() - 0.5);
629 double rndz = 2 * (rnd_geo.Rndm() - 0.5);
632 double x_gen =
fox + rndx *
fdx;
633 double y_gen =
foy + rndy *
fdy;
634 double z_gen =
foz + rndz *
fdz;
636 TLorentzVector pos(x_gen, y_gen, z_gen, t_gen);
640 return TLorentzVector( 0, 0, 0, 0);
650 <<
"Instantiating HNL generator.";
659 LOG(
"gevgen_pghnl",
pFATAL) <<
"Couldn't instantiate the HNL generator";
665 <<
"HNL generator instantiated successfully.";
678 <<
"Rest frame CoMLifetime = " <<
CoMLifetime <<
" [GeV^{-1}]";
681 for( std::vector< HNLDecayMode_t >::iterator it = intChannels->begin(); it != intChannels->end(); ++it ){
683 auto mapG = gammaMap.find( mode );
684 double theGamma = mapG->second;
689 std::map< HNLDecayMode_t, double > intMap =
695 std::map< HNLDecayMode_t, double > PMap =
700 double ranThrow = rnd->
RndGen().Uniform( 0., 1. );
705 int decay = ( int ) selectedDecayChan;
711 LOG(
"gevgen_pghnl",
pINFO) <<
"Parsing command line arguments";
718 bool help = parser.OptionExists(
'h');
726 char * expargv[ argc + 2 ];
727 bool didFindUserInputTune =
false;
730 if( parser.OptionExists(
"tune") ){
731 didFindUserInputTune =
true;
732 stExtraTuneBit = parser.ArgAsString(
"tune");
734 <<
"Using input HNL tune " << parser.ArgAsString(
"tune");
740 for(
int iArg = 0; iArg < argc; iArg++ ){
741 expargv[iArg] = argv[iArg];
743 if( !didFindUserInputTune ){
744 char * chBit =
const_cast< char *
>( stExtraTuneBit.c_str() );
745 std::string stune(
"--tune");
char * tBit =
const_cast< char *
>( stune.c_str() );
746 expargv[argc] = tBit;
747 expargv[argc+1] = chBit;
751 int expargc = ( didFindUserInputTune ) ? argc : argc+2;
752 std::string stnull(
"");
char * nBit =
const_cast< char *
>( stnull.c_str() );
753 expargv[expargc] = nBit;
758 if( parser.OptionExists(
'r') ) {
759 LOG(
"gevgen_pghnl",
pDEBUG) <<
"Reading MC run number";
762 LOG(
"gevgen_pghnl",
pDEBUG) <<
"Unspecified run number - Using default";
767 if( parser.OptionExists(
'n') ) {
769 <<
"Reading number of events to generate";
770 gOptNev = parser.ArgAsInt(
'n');
773 <<
"You need to specify the number of events";
780 const Decayer * hnlgen =
dynamic_cast< const Decayer *
>( algHNLGen );
785 if( parser.OptionExists(
'm') ) {
787 <<
"Reading HNL decay mode";
788 mode = parser.ArgAsInt(
'm');
791 <<
"No decay mode specified - will sample from allowed decay modes";
798 <<
"Specified decay is not allowed kinematically for the given HNL mass";
809 #ifdef __CAN_USE_ROOT_GEOM__
811 if( parser.OptionExists(
'g') ) {
812 LOG(
"gevgen_pghnl",
pDEBUG) <<
"Getting input geometry";
813 geom = parser.ArgAsString(
'g');
816 bool accessible_geom_file =
817 ! (gSystem->AccessPathName(geom.c_str()));
818 if (accessible_geom_file) {
823 <<
"Geometry option is not a ROOT file. Please use ROOT geom.";
838 if( parser.OptionExists(
'L') ) {
840 <<
"Checking for input geometry length units";
841 lunits = parser.ArgAsString(
'L');
843 LOG(
"gevgen_pghnl",
pDEBUG) <<
"Using default geometry length units";
859 #endif // #ifdef __CAN_USE_ROOT_GEOM__
862 if( parser.OptionExists(
'o') ) {
863 LOG(
"gevgen_pghnl",
pDEBUG) <<
"Reading the event filename prefix";
867 <<
"Will set the default event filename prefix";
872 if( parser.OptionExists(
"seed") ) {
873 LOG(
"gevgen_pghnl",
pINFO) <<
"Reading random number seed";
876 LOG(
"gevgen_pghnl",
pINFO) <<
"Unspecified random number seed - Using default";
884 ostringstream gminfo;
886 gminfo <<
"Using ROOT geometry - file: " <<
gOptRootGeom
889 <<
", length units: " <<
lunits;
901 <<
"\n @@ Geometry : " << gminfo.str()
902 <<
"\n @@ Statistics : " <<
gOptNev <<
" events";
909 <<
"\n gevgen_pghnl [-h] "
911 <<
"\n -n n_of_events"
912 <<
"\n [-m decay_mode]"
913 <<
"\n [-g geometry (ROOT file)]"
914 <<
"\n [-L length_units_at_geom]"
915 <<
"\n [-o output_event_file_prefix]"
916 <<
"\n [--seed random_number_seed]"
917 <<
"\n [--message-thresholds xml_file]"
918 <<
"\n [--event-record-print-level level]"
919 <<
"\n [--mc-job-status-refresh-rate rate]"
921 <<
" Please also read the detailed documentation at http://www.genie-mc.org"
922 <<
" or look at the source code: $GENIE/src/Apps/gBeamHNLParticleGun.cxx"
bool IsHNLMajorana() const
void RandGen(long int seed)
static void SetPrintLevel(int print_level)
HNLDecayMode_t gOptDecayMode
TLorentzVector GeneratePosition(GHepRecord *event)
Heavy Neutral Lepton final-state product generator.
Heavy Neutral Lepton decay vertex generator given production vertex and momentum ***.
void SetProbeP4(const TLorentzVector &P4)
static RandomGen * Instance()
Access instance.
string AsString(genie::hnl::HNLDecayMode_t hnldm)
Defines the EventRecordVisitorI interface. Concrete implementations of this interface use the 'Visito...
void ReadFromCommandLine(int argc, char **argv)
virtual void SetProbability(double prob)
string P4AsString(const TLorentzVector *p)
void Update(int iev, const EventRecord *event)
Algorithm abstract base class.
TLorentzVector * GenerateOriginPosition(GHepRecord *event)
A singleton holding random number generator classes. All random number generation in GENIE should tak...
int main(int argc, char **argv)
std::map< genie::hnl::HNLDecayMode_t, double > SetInterestingChannels(std::vector< genie::hnl::HNLDecayMode_t > intChannels, std::map< genie::hnl::HNLDecayMode_t, double > gammaMap)
double GetHNLMass() const
void SetRefreshRate(int rate)
string kDefOptEvFilePrefix
Summary information for an interaction.
Simple class to create & update MC job status files and env. vars. This is used to be able to keep tr...
double GetPGunEnergy() const
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
string gOptRootGeomTopVol
void ProcessEventRecord(GHepRecord *event_rec) const
std::vector< double > GetPGunDirection() const
double GetHNLLifetime() const
double UnitFromString(string u)
const Algorithm * GetAlgorithm(const AlgId &algid)
std::map< genie::hnl::HNLDecayMode_t, double > GetValidChannels()
enum genie::hnl::EHNLDecayMode HNLDecayMode_t
void Save(void)
get the even tree
void SetInterestingChannels(const std::map< genie::hnl::HNLDecayMode_t, double > gammaMap)
TLorentzVector * GenerateOriginMomentum(GHepRecord *event)
void AddEventRecord(int ievent, const EventRecord *ev_rec)
save the event tree
std::vector< double > GetPGunOrigin() const
std::vector< double > GetPGunDeviation() const
std::vector< double > GetPGunDOrigin() const
std::string GetHNLInterestingChannels() const
Generated Event Record. It is a GHepRecord object that can accept / be visited by EventRecordVisitorI...
void CustomizeFilenamePrefix(string prefix)
void Initialize(void)
add event
static RunOpt * Instance(void)
static AlgFactory * Instance()
A utility class to facilitate creating the GENIE MC Ntuple from the output GENIE GHEP event records...
static __attribute__((unused)) double fDecayGammas[]
std::map< genie::hnl::HNLDecayMode_t, double > GetProbabilities(std::map< genie::hnl::HNLDecayMode_t, double > gammaMap)
TRandom3 & RndGen(void) const
rnd number generator for generic usage
std::vector< double > GetHNLCouplings() const
NtpMCFormat_t kDefOptNtpFormat
InitialState * InitStatePtr(void) const
string PrintFramedMesg(string mesg, unsigned int nl=1, const char f='*')
int SelectDecayMode(std::vector< HNLDecayMode_t > *intChannels, SimpleHNL sh)
void MesgThresholds(string inpfile)
const EventRecordVisitorI * HNLGenerator(void)
Command line argument parser.
enum genie::ENtpMCFormat NtpMCFormat_t
genie::hnl::HNLDecayMode_t SelectChannelInclusive(std::map< genie::hnl::HNLDecayMode_t, double > Pmap, double ranThrow)
void GetCommandLineArgs(int argc, char **argv)
The GENIE Algorithm Factory.
void ProcessEventRecord(GHepRecord *event) const
void SetGeomFile(std::string geomfile) const
GENIE's GHEP MC event record.
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
STDHEP-like event record entry that can fit a particle or a nucleus.
bool IsKinematicallyAllowed(genie::hnl::HNLDecayMode_t hnldm, double Mhnl)
std::vector< HNLDecayMode_t > gOptIntChannels
static Interaction * HNL(int probe, double E=0, int decayed_mode=-1)