115using std::ostringstream;
117using namespace genie;
120#ifdef __GENIE_FLUX_DRIVERS_ENABLED__
121#define __CAN_GENERATE_EVENTS_USING_A_FLUX__
126#ifdef __GENIE_GEOM_DRIVERS_ENABLED__
127#define __CAN_USE_ROOT_GEOM__
128#include <TGeoVolume.h>
129#include <TGeoManager.h>
130#include <TGeoShape.h>
150#ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX__
151int TestFluxFromDk2nu (
void);
156#ifdef __CAN_USE_ROOT_GEOM__
158void InitBoundingBox (
void);
223#ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX__
225bool gOptIsUsingDk2nu =
false;
238#ifdef __CAN_USE_ROOT_GEOM__
239TGeoManager * gOptRootGeoManager = 0;
240TGeoVolume * gOptRootGeoVolume = 0;
255int main(
int argc,
char ** argv)
258 gErrorIgnoreLevel = kWarning;
274 case kValGeom:
return TestGeom();
break;
275 default:
LOG(
"gevald_hnl",
pFATAL ) <<
"I didn't recognise this mode. Goodbye world!";
break;
282#ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX__
283int TestFluxFromDk2nu()
287 string foutName(
"test_flux_dk2nu.root");
290 <<
"\n\nTesting flux prediction from dk2nu input files."
291 <<
"\nWill produce 1 ROOT file (" << foutName <<
") with:"
292 <<
"\n--> Energy spectra for the HNL (total and broken down by parent)"
293 <<
"\n--> Production vertex locations"
294 <<
"\n--> Counters for each production mode"
295 <<
"\n--> Spectrum of acceptance correction as function of parent boost factor"
296 <<
"\n--> Boost factor spectrum of parents broken down by type";
303 bool geom_is_accessible = ! (gSystem->AccessPathName(
gOptRootGeom.c_str()));
304 if (!geom_is_accessible) {
306 <<
"The specified ROOT geometry doesn't exist! Initialization failed!";
311 int maxFluxEntries = -1;
313 if( !gOptRootGeoManager ) gOptRootGeoManager = TGeoManager::Import(
gOptRootGeom.c_str());
315 TGeoVolume * top_volume = gOptRootGeoManager->GetTopVolume();
316 assert( top_volume );
317 TGeoShape * ts = top_volume->GetShape();
318 __attribute__((unused)) TGeoBBox * box = (TGeoBBox *)ts;
320 TFile * fout = TFile::Open( foutName.c_str(),
"RECREATE" );
321 TH1D hEAll, hEPion, hEKaon, hEMuon, hENeuk;
323 TH1D hAcceptanceCorr, hAcceptance, hAcceptNoBCorr;
326 TH1D hBAll, hBPion, hBKaon, hBMuon, hBNeuk;
329 hEAll = TH1D(
"hEAll",
"HNL energy - all parents", 1000, 0., 100. );
330 hEPion = TH1D(
"hEPion",
"HNL energy - pion parent", 1000, 0., 100. );
331 hEKaon = TH1D(
"hEKaon",
"HNL energy - kaon parent", 1000, 0., 100. );
332 hEMuon = TH1D(
"hEMuon",
"HNL energy - muon parent", 1000, 0., 100. );
333 hENeuk = TH1D(
"hENeuk",
"HNL energy - neuk parent", 1000, 0., 100. );
335 hPop = TH1D(
"hPop",
"HNL populations in energy bins", 1000, 0., 100. );
336 hImpwt = TH1D(
"hImpwt",
"HNL importance weights", 1000, 0., 100. );
338 static const Double_t accbins[] = { 0.0, 2.5e-7, 5.0e-7, 7.5e-7, 1.0e-6, 2.5e-6, 5.0e-6, 7.5e-6, 1.0e-5, 2.5e-5, 5.0e-5, 7.5e-5, 1.0e-4, 2.5e-4, 5.0e-4, 7.5e-4, 1.0e-3, 2.5e-3, 5.0e-3, 7.5e-3, 1.0e-2, 2.5e-2, 5.0e-2, 7.5e-2, 1.0e-1, 2.5e-1, 5.0e-1, 7.5e-1, 1.0e+0, 2.5e+0, 5.0e+0, 7.5e+0, 1.0e+1 };
339 const Int_t naccbins =
sizeof(accbins)/
sizeof(accbins[0]) - 1;
340 hAcceptanceCorr = TH1D(
"hAcceptanceCorr",
"HNL acceptance correction", naccbins, accbins );
341 hAcceptance = TH1D(
"hAcceptance",
"HNL acceptance" , 200, 0.0, 100.0 );
342 hAcceptNoBCorr = TH1D(
"hAcceptNoBCorr",
"HNL SAA * accCorr" , 200, 0.0, 100.0 );
344 hProdVtxPos = TH3D(
"hProdVtxPos",
"HNL production vertex (user coordinates, cm)",
345 200, -100., 100., 200, -100., 100., 1100, -110000., 0.);
347 hCounters = TH1D(
"hCounters",
"HNL production channel counters", 11, 0, 11 );
349 hBAll = TH1D(
"hBAll",
"Boost beta - all parents", 100, 0., 1. );
350 hBPion = TH1D(
"hBPion",
"Boost beta - pion parent", 100, 0., 1. );
351 hBKaon = TH1D(
"hBKaon",
"Boost beta - kaon parent", 100, 0., 1. );
352 hBMuon = TH1D(
"hBMuon",
"Boost beta - muon parent", 100, 0., 1. );
353 hBNeuk = TH1D(
"hBNeuk",
"Boost beta - neuk parent", 100, 0., 1. );
355 hParamSpace = TH1D(
"hParamSpace",
"Parameter space", 5, 0., 5. );
358 TLorentzVector p4HNL;
359 TLorentzVector x4HNL;
360 int nPion2Muon = 0, nPion2Electron = 0, nKaon2Muon = 0,
361 nKaon2Electron = 0, nKaon3Muon = 0, nKaon3Electron = 0,
362 nNeuk3Muon = 0, nNeuk3Electron = 0, nMuon3Numu = 0,
363 nMuon3Nue = 0, nMuon3Nutau = 0;
373 if( ievent % (
gOptNev / 1000) == 0 ){
374 int irat = ievent / (
gOptNev / 1000);
375 std::cerr << Form(
"%2.2f", 0.1 * irat) <<
" % ( " << ievent <<
" / "
376 <<
gOptNev <<
" ) \r" << std::flush;
379 if( ievent % (
gOptNev / 10) == 0 ){
380 int irat = ievent / (
gOptNev / 10 );
381 std::cerr << 10.0 * irat <<
" % " <<
" ( " << ievent
382 <<
" / " <<
gOptNev <<
" ) \r" << std::flush;
395 if(
gOptNev > maxFluxEntries ){
397 <<
"You have asked for " <<
gOptNev <<
" events, but only provided "
398 << maxFluxEntries <<
" flux entries. Truncating events to " << maxFluxEntries <<
".";
409 <<
"Skipping nonsense for event " << ievent <<
" (was this parent too light?)";
417 int typeMod = (gnmf->
pdg > 0) ? 1 : -1;
421 if( parPDG == 0 || parPDG == -9999 ){ ievent++;
continue; }
429 TLorentzVector p4par = gnmf->
parp4;
430 double EPar = p4par.E();
432 TVector3 boost_beta = p4par.BoostVector();
433 betaMag = boost_beta.Mag();
437 double delay = gnmf->
delay;
449 double gam = std::sqrt( 1.0 / ( 1.0 - betaMag * betaMag ) );
451 double betaStar = std::sqrt( 1.0 - 1.0 / ( gamStar * gamStar ) );
452 double bigBeta = betaMag * gam / betaStar;
454 double Ox = -1.0 * x4HNL.X();
455 double Oy = -1.0 * x4HNL.Y();
456 double Oz = -1.0 * x4HNL.Z();
458 double rootArg = gam*gam*Oz*Oz -
459 (gam*gam - bigBeta*bigBeta)*(Oz*Oz - bigBeta*bigBeta*(Ox*Ox + Oy*Oy));
461 double timelikeBit = ( rootArg >= 0.0 ) ? std::sqrt( rootArg ) / ( betaMag * gam * gam * gam ) : 0.0;
463 double fullTerm = (1.0 - 1.0 / gam) * Oz / ( betaMag * gam ) - timelikeBit;
464 if( std::abs( fullTerm ) > 100.0 ) fullTerm *= 100.0 / std::abs( fullTerm );
469 hEAll.Fill( p4HNL.E(), acceptance * nimpwt );
470 hProdVtxPos.Fill( x4HNL.X(), x4HNL.Y(), x4HNL.Z(), nimpwt );
471 hBAll.Fill( betaMag, nimpwt );
473 hPop.Fill( p4HNL.E(), 1.0 );
474 hImpwt.Fill( p4HNL.E(), nimpwt );
475 hAcceptanceCorr.Fill( accCorr, nimpwt );
476 hAcceptance.Fill( p4HNL.E(), nimpwt * acceptance );
477 hAcceptNoBCorr.Fill( p4HNL.E(), nimpwt * acceptance / ( bCorr * bCorr ) );
481 hEPion.Fill( p4HNL.E(), acceptance * nimpwt );
482 hBPion.Fill( betaMag, nimpwt );
485 hEKaon.Fill( p4HNL.E(), acceptance * nimpwt );
486 hBKaon.Fill( betaMag, nimpwt );
489 hENeuk.Fill( p4HNL.E(), acceptance * nimpwt );
490 hBNeuk.Fill( betaMag, nimpwt );
493 hEMuon.Fill( p4HNL.E(), acceptance * nimpwt );
494 hBMuon.Fill( betaMag, nimpwt );
499 <<
" *** Output for event no " << ievent <<
"... ***"
500 <<
"\nparPDG = " << parPDG
503 <<
" : mag = " << betaMag
506 <<
"\nacceptance = " << acceptance <<
" : accCorr = " << accCorr
507 <<
"\nnimpwt = " << nimpwt
519 hCounters.SetBinContent( 1, nPion2Muon );
520 hCounters.SetBinContent( 2, nPion2Electron );
521 hCounters.SetBinContent( 3, nKaon2Muon );
522 hCounters.SetBinContent( 4, nKaon2Electron );
523 hCounters.SetBinContent( 5, nKaon3Muon );
524 hCounters.SetBinContent( 6, nKaon3Electron );
525 hCounters.SetBinContent( 7, nNeuk3Muon );
526 hCounters.SetBinContent( 8, nNeuk3Electron );
527 hCounters.SetBinContent( 9, nMuon3Numu );
528 hCounters.SetBinContent( 10, nMuon3Nue );
529 hCounters.SetBinContent( 11, nMuon3Nutau );
531 hParamSpace.SetBinContent( 1, 1000.0 *
gCfgMassHNL );
535 hParamSpace.SetBinContent( 5, nPOT );
547 string foutName(
"test_decay.root");
549 TFile * fout = TFile::Open( foutName.c_str(),
"RECREATE" );
553 const Decayer * hnlgen =
dynamic_cast< const Decayer *
>( algHNLGen );
555 bool geom_is_accessible = ! (gSystem->AccessPathName(
gOptRootGeom.c_str()));
556 if (!geom_is_accessible) {
558 <<
"The specified ROOT geometry doesn't exist! Initialization failed!";
562 if( !gOptRootGeoManager ) gOptRootGeoManager = TGeoManager::Import(
gOptRootGeom.c_str());
564 TGeoVolume * top_volume = gOptRootGeoManager->GetTopVolume();
565 assert( top_volume );
566 TGeoShape * ts = top_volume->GetShape();
567 __attribute__((unused)) TGeoBBox * box = (TGeoBBox *)ts;
569 LOG(
"gevald_hnl",
pDEBUG ) <<
"Imported box.";
581 assert( valMap.size() > 0 );
585 <<
"\n\nTesting decay modes for the HNL."
586 <<
"\nWill process gOptNev = " <<
gOptNev <<
" x ( N_channels = " << valMap.size()
587 <<
" ) = " << valMap.size() *
gOptNev <<
" events, 1 for each valid channel."
588 <<
"\nWill produce 1 ROOT file ( " << foutName <<
" ) with:"
589 <<
"\n--> Energy spectrum for the decay products for each channel"
590 <<
"\n--> Rates of each decay channel";
599 assert( p3HNL >= 0.0 );
600 TLorentzVector * p4HNL =
new TLorentzVector( p3HNL *
gCfgHNLCx,
609 TLorentzVector * x4HNL =
new TLorentzVector( 1.0, 2.0, 3.0, 0.0 );
614 std::map< HNLDecayMode_t, double >::iterator vmit = valMap.begin();
int modeIdx = 0;
615 std::ostringstream msts;
616 for( ; vmit != valMap.end(); ++vmit ){
617 validModes[ modeIdx ] = (*vmit).first;
623 LOG(
"gevald_hnl",
pDEBUG ) <<
"Here are the modes in order : " << msts.str();
627 TH1D hSpectrum[10][3], hCMSpectrum[10][3], hRates;
628 TH1D hParamSpace = TH1D(
"hParamSpace",
"Parameter space", 5, 0., 5. );
630 hParamSpace.SetBinContent( 1, 1000.0 *
gCfgMassHNL );
635 hRates = TH1D(
"hRates",
"Rates of HNL decay channels", 10, 0, 10 );
637 std::string shortModes[10] = {
"vvv",
"vee",
"vmue",
"pi0v",
"pie",
"vmumu",
"pimu",
"pi0pi0v",
638 "pipi0e",
"pipi0mu" };
639 std::string part0names[10] = {
"v1",
"v",
"v",
"pi0",
"pi",
"v",
"pi",
"pi01",
"pi",
"pi" };
640 std::string part1names[10] = {
"v2",
"e1",
"mu",
"v",
"e",
"mu1",
"mu",
"pi02",
"pi0",
"pi0" };
641 std::string part2names[10] = {
"v3",
"e2",
"e",
"None",
"None",
"mu2",
"None",
"v",
"e",
"mu" };
642 std::string partNames[3][10] = { part0names, part1names, part2names };
643 for(
unsigned int iChan = 0; iChan < valMap.size(); iChan++ ){
645 std::string shortMode = shortModes[iChan];
647 for( Int_t iPart = 0; iPart < 3; iPart++ ){
648 std::string ParticleName = partNames[iPart][iChan];
649 if( strcmp( ParticleName.c_str(),
"None" ) != 0 ){
650 hSpectrum[iChan][iPart] = TH1D( Form(
"hSpectrum_%s_%s", shortMode.c_str(), ParticleName.c_str() ),
651 Form(
"Fractional energy of particle: %s in decay: %s",
652 ParticleName.c_str(),
655 hCMSpectrum[iChan][iPart] = TH1D( Form(
"hCMSpectrum_%s_%s", shortMode.c_str(), ParticleName.c_str() ),
656 Form(
"Rest frame energy of particle: %s in decay: %s",
657 ParticleName.c_str(),
667 double rnuee = ( valMap.find(
kHNLDcyNuEE ) != valMap.end() ) ? (*(valMap.find(
kHNLDcyNuEE ))).second : 0.0;
670 double rpie = ( valMap.find(
kHNLDcyPiE ) != valMap.end() ) ? (*(valMap.find(
kHNLDcyPiE ))).second : 0.0;
672 double rpimu = ( valMap.find(
kHNLDcyPiMu ) != valMap.end() ) ? (*(valMap.find(
kHNLDcyPiMu ))).second : 0.0;
677 hRates.SetBinContent( 1, rpimu );
678 hRates.SetBinContent( 2, rpie );
679 hRates.SetBinContent( 3, rpi0nu );
680 hRates.SetBinContent( 4, rnununu );
681 hRates.SetBinContent( 5, rnumumu );
682 hRates.SetBinContent( 6, rnuee );
683 hRates.SetBinContent( 7, rnumue );
684 hRates.SetBinContent( 8, rpipi0e );
685 hRates.SetBinContent( 9, rpipi0mu );
686 hRates.SetBinContent( 10, rpi0pi0nu );
692 if( ievent % (
gOptNev / 1000) == 0 ){
693 int irat = ievent / (
gOptNev / 1000);
694 std::cerr << Form(
"%2.2f", 0.1 * irat) <<
" % ( " << ievent <<
" / "
695 <<
gOptNev <<
" ) \r" << std::flush;
698 if( ievent % (
gOptNev / 10) == 0 ){
699 int irat = ievent / (
gOptNev / 10 );
700 std::cerr << 10.0 * irat <<
" % " <<
" ( " << ievent
701 <<
" / " <<
gOptNev <<
" ) \r" << std::flush;
705 if( ievent ==
gOptNev ){ std::cerr <<
" \n";
break; }
708 for(
unsigned int iMode = 0; iMode < valMap.size(); iMode++ ){
719 event->AddParticle( ptHNL );
721 event->SetVertex( *x4HNL );
725 event->AttachSummary( interaction );
727 <<
"Simulating decay with mode "
737 double ox = PGOrigin.at(0), oy = PGOrigin.at(1), oz = PGOrigin.at(2);
744 TVector3 startPoint( ox, oy, oz ); TVector3 entryPoint, exitPoint;
745 TLorentzVector tmpVtx( ox, oy, oz, 0.0 );
746 event->SetVertex( tmpVtx );
753 double wgt =
event->Weight();
754 hSpectrum[iMode][0].Fill( (event->Particle(1))->E() /
gOptEnergyHNL, wgt );
755 hSpectrum[iMode][1].Fill( (event->Particle(2))->E() /
gOptEnergyHNL, wgt );
756 if( event->Particle(3) ) hSpectrum[iMode][2].Fill( (event->Particle(3))->E() /
gOptEnergyHNL, wgt );
760 TLorentzVector * p4p1 = (
event->Particle(1))->GetP4();
761 TLorentzVector * p4p2 = (
event->Particle(2))->GetP4();
762 TLorentzVector * p4p3 = 0;
763 if( event->Particle(3) ) p4p3 = (
event->Particle(3))->GetP4();
765 TVector3 boostVec = p4HNL->BoostVector();
767 p4p1->Boost( -boostVec );
768 p4p2->Boost( -boostVec );
769 if( p4p3 ) p4p3->Boost( -boostVec );
771 hCMSpectrum[iMode][0].Fill( p4p1->E(), wgt );
772 hCMSpectrum[iMode][1].Fill( p4p2->E(), wgt );
773 if( p4p3 ) hCMSpectrum[iMode][2].Fill( p4p3->E(), wgt );
780 if( ievent == 0 )
LOG(
"gevald_hnl",
pDEBUG ) << asts.str();
781 LOG(
"gevald_hnl",
pDEBUG ) <<
"Finished event: " << ievent;
790 for(
unsigned int i = 0; i < valMap.size(); i++ ){
791 for( Int_t j = 0; j < 3; j++ ){
792 std::string ParticleName = partNames[j][i];
793 if( strcmp( ParticleName.c_str(),
"None" ) != 0 ){
794 hSpectrum[i][j].Write();
795 hCMSpectrum[i][j].Write();
807#ifdef __CAN_USE_ROOT_GEOM__
811 string foutName(
"test_geom.root");
813 TFile * fout = TFile::Open( foutName.c_str(),
"RECREATE" );
816 <<
"\n\nTesting ROOT geometry for ROOT file " <<
gOptRootGeom
817 <<
"\nWill produce 1 ROOT file ( " << foutName <<
" ) with:"
818 <<
"\n--> Specified geometry"
819 <<
"\n--> TTree containing the following branch structure:"
821 <<
"\n |---- start x,y,z [mm]"
823 <<
"\n |---- HNL 4-momentum [GeV]"
825 <<
"\n |---- did intersect detector?"
827 <<
"\n |---- entry x,y,z [mm]"
829 <<
"\n |---- exit x,y,z [mm]"
833 <<
"\n |---- HNL lifetime (rest frame) [ns]"
835 <<
"\n |---- HNL lifetime (lab frame) [ns]"
837 <<
"\n |---- decay x,y,z [mm]"
838 <<
"\n--> Weight histogram"
839 <<
"\n--> Travel-length histogram"
841 <<
"\n(where same coordinate system as user's is used and weight == P(HNL decays in detector) )";
843 double dev_start[3] = { -9999.9, -9999.9, -9999.9 };
844 double dev_sphere[2] = { -9999.9, -9999.9 };
845 double use_start[3] = { -9999.9, -9999.9, -9999.9 };
846 double use_entry[3] = { -9999.9, -9999.9, -9999.9 };
847 double use_exit[3] = { -9999.9, -9999.9, -9999.9 };
848 double use_decay[3] = { -9999.9, -9999.9, -9999.9 };
849 double use_momentum[4] = { -9999.9, -9999.9, -9999.9, -9999.9 };
850 double use_wgt = -9999.9;
851 double use_lifetime = -9999.9, use_CMlifetime = -9999.9;
852 bool didIntersectDet =
false;
854 TTree * outTree =
new TTree(
"outTree",
"Trajectory information tree" );
855 outTree->Branch(
"startPoint", use_start,
"startPoint[3]/D" );
856 outTree->Branch(
"fourMomentum", use_momentum,
"fourMomentum[4]/D" );
857 outTree->Branch(
"startDeviate", dev_start,
"startDeviate[3]/D" );
858 outTree->Branch(
"spherDeviate", dev_sphere,
"spherDeviate[2]/D" );
859 outTree->Branch(
"didIntersect", &didIntersectDet,
"didIntersect/O" );
860 outTree->Branch(
"entryPoint", use_entry,
"entryPoint[3]/D" );
861 outTree->Branch(
"exitPoint", use_exit,
"exitPoint[3]/D" );
862 outTree->Branch(
"decayPoint", use_decay,
"decayPoint[3]/D" );
863 outTree->Branch(
"weight", &use_wgt,
"weight/D" );
864 outTree->Branch(
"lifetime_LAB", &use_lifetime,
"lifetime_LAB/D" );
865 outTree->Branch(
"lifetime_CM", &use_CMlifetime,
"lifetime_CM/D" );
867 TH1D hWeight(
"hWeight",
"Log_{10} ( P( decay in detector ) )",
869 TH1D hLength(
"hLength",
"Length travelled in detector / max possible length in detector",
872 bool geom_is_accessible = ! (gSystem->AccessPathName(
gOptRootGeom.c_str()));
873 if (!geom_is_accessible) {
875 <<
"The specified ROOT geometry doesn't exist! Initialization failed!";
879 gOptRootGeoManager = TGeoManager::Import(
gOptRootGeom.c_str());
880 TGeoVolume * top_volume = gOptRootGeoManager->GetTopVolume();
881 assert( top_volume );
889 const Decayer * hnlgen =
dynamic_cast< const Decayer *
>( algHNLGen );
901 assert( p3HNL >= 0.0 );
902 TLorentzVector * p4HNL =
new TLorentzVector( p3HNL *
gCfgHNLCx,
911 double betaMag = p4HNL->P() / p4HNL->E();
912 __attribute__((unused))
double gamma = std::sqrt( 1.0 / ( 1.0 - betaMag * betaMag ) );
921 const double PGox = PGOrigin.at(0), PGoy = PGOrigin.at(1), PGoz = PGOrigin.at(2);
922 const double PGdx = PGDOrigin.at(0), PGdy = PGDOrigin.at(1), PGdz = PGDOrigin.at(2);
933 assert( PGdx > 0.0 && PGdy > 0.0 && PGdz > 0.0 );
940 const double PGtheta = std::acos( PGcz );
942 ( PGcy >= 0.0 ) ? std::acos( PGcx / PGcz ) : 2.0 *
constants::kPi - std::acos( PGcx / PGcz );
945 const double PGdtheta = PGDeviation.at(0) *
constants::kPi / 180.0;
963 const int NCARTESIAN = 5;
964 const int NSPHERICAL = 9;
965 const int NMAX = NCARTESIAN * NCARTESIAN * NCARTESIAN * NSPHERICAL * NSPHERICAL;
967 double arr_ox[ NCARTESIAN ] = { PGox - PGdx, PGox - PGdx/2.0, PGox, PGox + PGdx/2.0, PGox + PGdx };
968 double arr_oy[ NCARTESIAN ] = { PGoy - PGdy, PGoy - PGdy/2.0, PGoy, PGoy + PGdy/2.0, PGoy + PGdy };
969 double arr_oz[ NCARTESIAN ] = { PGoz - PGdz, PGoz - PGdz/2.0, PGoz, PGoz + PGdz/2.0, PGoz + PGdz };
971 double arr_theta[ NSPHERICAL ] = { PGtheta - PGdtheta, PGtheta - 3.0/4.0 * PGdtheta, PGtheta - 1.0/2.0 * PGdtheta, PGtheta - 1.0/4.0 * PGdtheta, PGtheta, PGtheta + 1.0/4.0 * PGdtheta, PGtheta + 1.0/2.0 * PGdtheta, PGtheta + 3.0/4.0 * PGdtheta, PGtheta + PGdtheta };
972 double arr_phi[ NSPHERICAL ] = { PGphi - PGdphi, PGphi - 3.0/4.0 * PGdphi, PGphi - 1.0/2.0 * PGdphi, PGphi - 1.0/4.0 * PGdphi, PGphi, PGphi + 1.0/4.0 * PGdphi, PGphi + 1.0/2.0 * PGdphi, PGphi + 3.0/4.0 * PGdphi, PGphi + PGdphi };
976 if( !gOptRootGeoManager ) gOptRootGeoManager = TGeoManager::Import(
gOptRootGeom.c_str());
978 TGeoShape * ts = top_volume->GetShape();
979 __attribute__((unused)) TGeoBBox * box = (TGeoBBox *)ts;
985 if( ievent == NMAX )
break;
988 <<
"*** Building event = " << ievent;
993 event->AttachSummary( interaction );
1001 int ix = ievent % NCARTESIAN;
1002 int iy = ( ievent / NCARTESIAN ) % NCARTESIAN;
1003 int iz = ( ievent / NCARTESIAN / NCARTESIAN ) % NCARTESIAN;
1004 int ip = ( ievent / NCARTESIAN / NCARTESIAN / NCARTESIAN ) % NSPHERICAL;
1005 int it = ( ievent / NCARTESIAN / NCARTESIAN / NCARTESIAN / NSPHERICAL ) % NSPHERICAL;
1015 double use_theta = arr_theta[ it ];
1016 double use_phi = arr_phi[ ip ];
1021 double use_cx = std::cos( use_phi ) * std::sin( use_theta );
1022 double use_cy = std::sin( use_phi ) * std::sin( use_theta );
1023 double use_cz = std::cos( use_theta );
1026 p4HNL->SetPxPyPzE( p3HNL * use_cx, p3HNL * use_cy, p3HNL * use_cz,
gOptEnergyHNL );
1028 TVector3 startPoint, momentum;
1029 TVector3 entryPoint, exitPoint, decayPoint;
1031 startPoint.SetXYZ( use_ox, use_oy, use_oz );
1032 momentum.SetXYZ( p4HNL->Px(), p4HNL->Py(), p4HNL->Pz() );
1034 use_start[0] = use_ox;
1035 use_start[1] = use_oy;
1036 use_start[2] = use_oz;
1038 use_momentum[0] = p4HNL->Px();
1039 use_momentum[1] = p4HNL->Py();
1040 use_momentum[2] = p4HNL->Pz();
1041 use_momentum[3] = p4HNL->E();
1050 TLorentzVector tmpVtx( use_ox, use_oy, use_oz, 0.0);
1051 event->SetVertex( tmpVtx );
1052 TLorentzVector tmpMom = *p4HNL;
1054 event->AddParticle( ptHNL );
1060 if( event->Vertex()->T() != -999.9 ){
1061 decayPoint.SetXYZ( event->Vertex()->X(), event->Vertex()->Y(), event->Vertex()->Z() );
1062 entryPoint.SetXYZ( event->Particle(1)->Vx(), event->Particle(1)->Vy(), event->Particle(1)->Vz() );
1063 exitPoint.SetXYZ( event->Particle(2)->Vx(), event->Particle(2)->Vy(), event->Particle(2)->Vz() );
1064 use_wgt =
event->Weight();
1067 use_entry[0] = entryPoint.X();
1068 use_entry[1] = entryPoint.Y();
1069 use_entry[2] = entryPoint.Z();
1071 use_exit[0] = exitPoint.X();
1072 use_exit[1] = exitPoint.Y();
1073 use_exit[2] = exitPoint.Z();
1075 use_decay[0] = decayPoint.X();
1076 use_decay[1] = decayPoint.Y();
1077 use_decay[2] = decayPoint.Z();
1083 double mdeX = exitPoint.X() - entryPoint.X();
1084 double mdeY = exitPoint.Y() - entryPoint.Y();
1085 double mdeZ = exitPoint.Z() - entryPoint.Z();
1087 double elapsedLength = std::sqrt( devX * devX + devY * devY + devZ * devZ );
1088 double maxLength = std::sqrt( mdeX * mdeX + mdeY * mdeY + mdeZ * mdeZ );
1091 hWeight.Fill( -1.0 * std::log10( use_wgt ), 1.0 );
1092 hLength.Fill( elapsedLength / maxLength );
1093 didIntersectDet =
true;
1097 use_entry[0] = -999.9;
1098 use_entry[1] = -999.9;
1099 use_entry[2] = -999.9;
1101 use_exit[0] = -999.9;
1102 use_exit[1] = -999.9;
1103 use_exit[2] = -999.9;
1105 use_decay[0] = -999.9;
1106 use_decay[1] = -999.9;
1107 use_decay[2] = -999.9;
1109 didIntersectDet =
false;
1127void InitBoundingBox(
void)
1132 <<
"Initialising geometry bounding box.";
1143 bool geom_is_accessible = ! (gSystem->AccessPathName(
gOptRootGeom.c_str()));
1144 if (!geom_is_accessible) {
1146 <<
"The specified ROOT geometry doesn't exist! Initialization failed!";
1150 if( !gOptRootGeoManager ) gOptRootGeoManager = TGeoManager::Import(
gOptRootGeom.c_str());
1152 TGeoVolume * top_volume = gOptRootGeoManager->GetTopVolume();
1153 assert( top_volume );
1154 TGeoShape * ts = top_volume->GetShape();
1155 TGeoBBox * box = (TGeoBBox *)ts;
1161 fox = (box->GetOrigin())[0];
1162 foy = (box->GetOrigin())[1];
1163 foz = (box->GetOrigin())[2];
1166 <<
"Before conversion the bounding box has:"
1167 <<
"\nOrigin = ( " <<
fox <<
" , " <<
foy <<
" , " <<
foz <<
" )"
1168 <<
"\nDimensions = " <<
fdx <<
" x " <<
fdy <<
" x " <<
fdz
1169 <<
"\n1cm = 1.0 unit";
1180 <<
"Initialised bounding box successfully.";
1194 <<
"Instantiating HNL generator.";
1203 LOG(
"gevald_hnl",
pFATAL) <<
"Couldn't instantiate the HNL generator";
1209 <<
"HNL generator instantiated successfully.";
1216 LOG(
"gevald_hnl",
pINFO) <<
"Parsing command line arguments";
1231 char * expargv[ argc + 2 ];
1232 bool didFindUserInputTune =
false;
1236 didFindUserInputTune =
true;
1239 <<
"Using input HNL tune " << parser.
ArgAsString(
"tune");
1245 for(
int iArg = 0; iArg < argc; iArg++ ){
1246 expargv[iArg] = argv[iArg];
1248 if( !didFindUserInputTune ){
1249 char * chBit =
const_cast< char *
>( stExtraTuneBit.c_str() );
1250 std::string stune(
"--tune");
char * tBit =
const_cast< char *
>( stune.c_str() );
1251 expargv[argc] = tBit;
1252 expargv[argc+1] = chBit;
1256 int expargc = ( didFindUserInputTune ) ? argc : argc+2;
1257 std::string stnull(
"");
char * nBit =
const_cast< char *
>( stnull.c_str() );
1258 expargv[expargc] = nBit;
1264 LOG(
"gevald_hnl",
pDEBUG) <<
"Reading MC run number";
1267 LOG(
"gevald_hnl",
pDEBUG) <<
"Unspecified run number - Using default";
1274 <<
"Reading number of events to generate";
1278 <<
"You need to specify the number of events";
1285 <<
"Detecting mode. . .";
1289 <<
"You must specify a validation mode.";
1294 bool isMonoEnergeticFlux =
true;
1295#ifdef __CAN_GENERATE_EVENTS_USING_A_FLUX__
1298 <<
"A flux has been offered. Searching this path: " << parser.
ArgAsString(
'f');
1299 isMonoEnergeticFlux =
false;
1304 if( gSystem->OpenDirectory( gOptFluxFilePath.c_str() ) != NULL ){
1305 gOptIsUsingDk2nu =
true;
1307 <<
"dk2nu flux files detected. Will create flux spectrum dynamically.";
1310 <<
"Invalid flux file path " << gOptFluxFilePath;
1316 <<
"No flux file offered. Assuming monoenergetic flux.";
1321#ifdef __CAN_USE_ROOT_GEOM__
1323 LOG(
"gevald_hnl",
pDEBUG) <<
"Getting input geometry";
1327 bool accessible_geom_file =
1328 ! (gSystem->AccessPathName(
geom.c_str()));
1329 if (accessible_geom_file) {
1334 <<
"Geometry option is not a ROOT file. Please use ROOT geom.";
1341 <<
"No geometry option specified - Exiting";
1348 LOG(
"gevald_hnl",
pDEBUG) <<
"Setting length units to " <<
lunits.c_str();
1350 LOG(
"gevald_hnl",
pDEBUG) <<
"Using default geometry length units";
1357 LOG(
"gevald_hnl",
pDEBUG) <<
"Setting angle units to " <<
aunits.c_str();
1359 LOG(
"gevald_hnl",
pDEBUG) <<
"Using default angle length units";
1366 LOG(
"gevald_hnl",
pDEBUG) <<
"Setting time units to " <<
tunits.c_str();
1368 LOG(
"gevald_hnl",
pDEBUG) <<
"Using default geometry time units";
1377 LOG(
"gevald_hnl",
pDEBUG) <<
"Reading the event filename prefix";
1381 <<
"Will set the default event filename prefix";
1387 LOG(
"gevald_hnl",
pINFO) <<
"Reading random number seed";
1390 LOG(
"gevald_hnl",
pINFO) <<
"Unspecified random number seed - Using default";
1398 ostringstream gminfo;
1400 gminfo <<
"Using ROOT geometry - file: " <<
gOptRootGeom
1403 <<
", length units: " <<
lunits;
1416 <<
"\n @@ Flux path : " << gOptFluxFilePath
1417 <<
"\n @@ Geometry : " << gminfo.str()
1418 <<
"\n @@ Statistics : " <<
gOptNev <<
" events";
1424 <<
"Reading in validation configuration. . .";
1427 __attribute__((unused))
const Decayer * hnlgen =
dynamic_cast< const Decayer *
>( algHNLGen );
1449 double dircosMag2 = std::pow(
gCfgHNLCx, 2.0 ) +
1452 double invdircosmag = 1.0 / std::sqrt( dircosMag2 );
1459 while( stIntChannels.size() > 0 ){
1462 std::string tmpSt = stIntChannels.substr( stIntChannels.size()-1, stIntChannels.size() );
1463 if( std::strcmp( tmpSt.c_str(),
"1" ) == 0 )
1466 stIntChannels.erase( stIntChannels.end()-1, stIntChannels.end() );
1470 __attribute__((unused))
const FluxCreator * fluxCreator =
dynamic_cast< const FluxCreator *
>( algFluxCreator );
1474 std::vector< double > b2uRotation = fluxCreator->
GetB2URotation();
1487 csts <<
"Read out the following config:"
1494 <<
"\nInteresting decay channels:";
1495 for( std::vector< HNLDecayMode_t >::iterator chit =
gCfgIntChannels.begin();
1498 <<
"\nUser origin in beam coordinates = ( " <<
gCfgUserOx
1500 <<
"\nEuler extrinsic x-z-x rotation = ( " <<
gCfgUserAx1
1503 <<
", " <<
gCfgHNLCz <<
") [ GeV / GeV ]";
1505 LOG(
"gevald_hnl",
pDEBUG) << csts.str();
1513 <<
"\n gevald_hnl [-h] "
1515 <<
"\n -n n_of_events"
1516 <<
"\n [-f path_to_flux_files]"
1517 <<
"\n [-g geometry_file]"
1519 <<
"\n 1: Flux prediction from dk2nu files. Needs -f option"
1520 <<
"\n 2: HNL decay validation. Specify an origin point and 4-momentum"
1521 <<
"\n in the \"ParticleGun\" section in config. Needs -g option."
1522 <<
"\n 3: Custom geometry file validation. Needs -g option"
1523 <<
"\n Specify origin, momentum, and wiggle room for both of these in the"
1524 <<
"\n \"ParticleGun\" section in config"
1525 <<
"\n Regardless of how many events you ask for, this will evaluate 125x81"
1526 <<
"\n events: 5^3 from wiggling origin and 9^2 from wiggling momentum direction"
1527 <<
"\n 4: Full simulation (like gevgen_hnl but with lots of debug!)"
1529 <<
"\n The configuration file lives at $GENIE/config/CommonHNL.xml - see"
1530 <<
" <param_set name=\"Validation\">"
1532 <<
"\n Please also read the detailed documentation at http://www.genie-mc.org"
1533 <<
"\n or look at the source code: $GENIE/src/Apps/gBeamHNLValidationApp.cxx"
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE,...
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils.
The GENIE Algorithm Factory.
const Algorithm * GetAlgorithm(const AlgId &algid)
static AlgFactory * Instance()
Algorithm abstract base class.
Command line argument parser.
string ArgAsString(char opt)
bool OptionExists(char opt)
was option set?
Defines the EventRecordVisitorI interface. Concrete implementations of this interface use the 'Visito...
Generated Event Record. It is a GHepRecord object that can accept / be visited by EventRecordVisitorI...
STDHEP-like event record entry that can fit a particle or a nucleus.
virtual void SetXSec(double xsec)
static void SetPrintLevel(int print_level)
void SetProbeP4(const TLorentzVector &P4)
Summary information for an interaction.
const XclsTag & ExclTag(void) const
InitialState * InitStatePtr(void) const
static Interaction * HNL(int probe, double E=0, int decayed_mode=-1)
static PDGLibrary * Instance(void)
TParticlePDG * Find(int pdgc, bool must_exist=true)
void ReadFromCommandLine(int argc, char **argv)
static RunOpt * Instance(void)
int DecayMode(void) const
Heavy Neutral Lepton final-state product generator.
std::vector< double > GetPGunDirection() const
std::vector< double > GetPGunDeviation() const
std::string GetHNLInterestingChannels() const
double GetHNLMass() const
void ProcessEventRecord(GHepRecord *event) const
double GetHNLLifetime() const
bool IsHNLMajorana() const
double GetPGunEnergy() const
std::vector< double > GetPGunDOrigin() const
std::vector< double > GetPGunOrigin() const
std::vector< double > GetHNLCouplings() const
A GENIE flux container specific for HNL containers. Based on the dk2nu flux paradigm and genie::flux:...
double nimpwt
Weight of parent.
double Ecm
Parent rest-frame energy of HNL [GeV].
double delay
delay HNL would have wrt SMv [ns]
int prodChan
Decay mode that produced HNL.
TLorentzVector parp4
parent momentum at HNL production in NEAR coords [GeV/c]
int parPdg
parent PDG code
double accCorr
acceptance correction (collimation effect. SM v == 1)
double boostCorr
boost correction wrt parent rest-frame (ELAB = ECM * boostCorr)
TVector3 startPoint
parent decay vertex in NEAR coords [m]
TLorentzVector p4
HNL momentum in NEAR coords [GeV/c].
double acceptance
full acceptance == XYWgt * boostCorr^2 * accCorr
Calculates HNL production kinematics & production vertex. Is a concrete implementation of the FluxRec...
int GetNFluxEntries() const
void ProcessEventRecord(GHepRecord *event_rec) const
FluxContainer RetrieveFluxInfo() const
void SetGeomFile(string geomfile) const
std::vector< double > GetB2URotation() const
std::vector< double > GetB2UTranslation() const
void SetInputFluxPath(std::string finpath) const
void SetMomentumDirection(double ux, double uy, double uz)
std::map< genie::hnl::HNLDecayMode_t, double > GetValidChannels()
void SetEnergy(const double E)
Heavy Neutral Lepton decay vertex generator given production vertex and momentum ***.
void SetGeomFile(std::string geomfile) const
void ProcessEventRecord(GHepRecord *event_rec) const
string kDefOptEvFilePrefix
NtpMCFormat_t kDefOptNtpFormat
string gOptRootGeomTopVol
string kDefOptFluxFilePath
enum t_HNLValidation HNLValidation_t
HNLValidation_t gOptValidationMode
HNLDecayMode_t gCfgDecayMode
const EventRecordVisitorI * HNLGenerator(void)
void GetCommandLineArgs(int argc, char **argv)
std::vector< HNLDecayMode_t > gCfgIntChannels
static const double kASmallNum
enum genie::hnl::t_HNLProd HNLProd_t
enum genie::hnl::EHNLDecayMode HNLDecayMode_t
static constexpr double cm
static constexpr double m
static constexpr double ns
static constexpr double GeV
static constexpr double mm
static constexpr double rad
void RandGen(long int seed)
void MesgThresholds(string inpfile)
string ProdAsString(genie::hnl::HNLProd_t hnlprod)
string AsString(genie::hnl::HNLDecayMode_t hnldm)
string Vec3AsString(const TVector3 *vec)
string PrintFramedMesg(string mesg, unsigned int nl=1, const char f=' *')
string X4AsString(const TLorentzVector *x)
string P4AsString(const TLorentzVector *p)
double UnitFromString(string u)
THE MAIN GENIE PROJECT NAMESPACE
enum genie::ENtpMCFormat NtpMCFormat_t