101 #include <TRotation.h>
105 #include <TLorentzVector.h>
129 #ifdef __GENIE_FLUX_DRIVERS_ENABLED__
137 using std::ostringstream;
139 using namespace genie;
140 using namespace genie::flux;
141 using namespace genie::constants;
148 TH1D *
GetEmuPdf (
double Enu,
double costheta,
const TH3D* pdf3d);
164 const double a = 2
e+6;
165 const double e = 500
e+9;
172 int main(
int argc,
char** argv)
178 LOG(
"gmkspl",
pFATAL) <<
" No TuneId in RunOption";
193 TTree * ntupmuflux =
new TTree(
"ntupmuflux",
"GENIE Upgoing Muon Event Tree");
199 double brCosTheta = 0;
200 double brWghtFlxNu = 0;
201 double brWghtEmuPdf = 0;
206 ntupmuflux->Branch(
"iev", &brIev,
"iev/I" );
207 ntupmuflux->Branch(
"nu_code", &brNuCode,
"nu_code/I" );
208 ntupmuflux->Branch(
"Emu", &brEmu,
"Emu/D" );
209 ntupmuflux->Branch(
"Enu", &brEnu,
"Enu/D" );
210 ntupmuflux->Branch(
"costheta", &brCosTheta,
"costheta/D" );
211 ntupmuflux->Branch(
"wght_fluxnu", &brWghtFlxNu,
"wght_fluxnu/D" );
212 ntupmuflux->Branch(
"wght_emupdf", &brWghtEmuPdf,
"wght_emupdf/D" );
213 ntupmuflux->Branch(
"vx", &brVx,
"vx/D" );
214 ntupmuflux->Branch(
"vy", &brVy,
"vy/D" );
215 ntupmuflux->Branch(
"vz", &brVz,
"vz/D" );
216 ntupmuflux->Branch(
"xsec", &brXSec,
"xsec/D" );
224 for(brIev = 0; brIev <
gOptNev; brIev++) {
230 brNuCode = flux_driver->
PdgCode();
231 brEnu = flux_driver->
Momentum().E();
232 brCosTheta = -1. * flux_driver->
Momentum().Pz() / flux_driver->
Momentum().Vect().Mag();
233 brWghtFlxNu = flux_driver->
Weight();
236 <<
"Generated flux neutrino: code = " << brNuCode
237 <<
", Ev = " << brEnu <<
" GeV"
238 <<
", cos(theta) = " << brCosTheta
239 <<
", weight = " << brWghtFlxNu;
242 TH3D * pdf3d = (brNuCode ==
kPdgNuMu) ? pdf3d_numu : pdf3d_numubar;
243 TH1D * pdfEmu =
GetEmuPdf(brEnu,brCosTheta,pdf3d);
246 brEmu = pdfEmu->GetRandom();
247 brWghtEmuPdf = pdfEmu->Integral(
"width");
249 <<
"Selected muon has energy Emu = " << brEmu
250 <<
" and Emu pdg weight = " << brWghtEmuPdf;
260 <<
"Generated muon position: (" << brVx <<
", " << brVy <<
", " << brVz <<
") m";
274 ostringstream outfname;
275 outfname <<
"./genie." <<
gOptRunNu <<
".upmu.root";
276 TFile outf(outfname.str().c_str(),
"recreate");
277 ntupmuflux ->
Write(
"ntupmu");
278 pdf3d_numu ->
Write(
"pdf3d_numu");
279 pdf3d_numubar ->
Write(
"pdf3d_numubar");
306 double sintheta = TMath::Sqrt(1-costheta*costheta);
307 double cosphi = TMath::Cos(phi);
308 double sinphi = TMath::Sin(phi);
311 double z = rad * costheta;
312 double y = rad * sintheta * cosphi;
313 double x = rad * sintheta * sinphi;
318 TVector3 dvec1 = vec.Orthogonal();
319 TVector3 dvec2 = dvec1;
320 dvec2.Rotate(-
kPi/2.0,vec);
324 double random = rnd->
RndFlux().Rndm();
325 dvec1.SetMag(TMath::Sqrt(random)*rad_trans*TMath::Cos(psi));
326 dvec2.SetMag(TMath::Sqrt(random)*rad_trans*TMath::Sin(psi));
327 x += dvec1.X() + dvec2.X();
328 y += dvec1.Y() + dvec2.Y();
329 z += dvec1.Z() + dvec2.Z();
334 double pz = Enu * costheta;
335 double py = Enu * sintheta * sinphi;
336 double px = Enu * sintheta * cosphi;
337 TVector3 p3(-px,-py,-pz);
342 TVector3 Hit3(0,0,0);
345 bool HitFound =
false;
347 TVector3 unit(0,0,0);
349 double unitx = unit.X();
350 double unity = unit.Y();
351 double unitz = unit.Z();
354 if (x3.Z() < -l/2 && unitz > 0 && !HitFound){
355 while (temp3.Z() < -l/2){
358 if ( -l/2<temp3.X() && l/2>temp3.X() && -l/2<temp3.Y() && l/2>temp3.Y() ){
359 Hit3.SetXYZ(temp3.X(),temp3.Y(),-l/2);
366 if (x3.X() > l/2 && unitx < 0 && !HitFound){
367 while (temp3.X() > l/2){
370 if ( -l/2<temp3.Y() && l/2>temp3.Y() && -l/2<temp3.Z() && l/2>temp3.Z() ){
371 Hit3.SetXYZ(l/2,temp3.Y(),temp3.Z());
378 if (x3.Y() > l/2 && unity < 0 && !HitFound){
379 while (temp3.Y() > l/2){
382 if ( -l/2<temp3.X() && l/2>temp3.X() && -l/2<temp3.Z() && l/2>temp3.Z() ){
383 Hit3.SetXYZ(temp3.X(),l/2,temp3.Z());
390 if (x3.X() < -l/2 && unitx > 0 && !HitFound){
391 while (temp3.X() < -l/2){
394 if ( -l/2<temp3.Y() && l/2>temp3.Y() && -l/2<temp3.Z() && l/2>temp3.Z() ){
395 Hit3.SetXYZ(-l/2,temp3.Y(),temp3.Z());
402 if (x3.Y() < -l/2 && unity > 0 && !HitFound){
403 while (temp3.Y() < -l/2){
406 if ( -l/2<temp3.X() && l/2>temp3.X() && -l/2<temp3.Z() && l/2>temp3.Z() ){
407 Hit3.SetXYZ(temp3.X(),-l/2,temp3.Z());
422 LOG(
"gevgen_upmu",
pINFO) <<
"Pulling next neurtino from the flux driver...";
425 int nu_code = flux_driver->
PdgCode();
427 const TLorentzVector & p4 = flux_driver->
Momentum();
428 double costheta = -p4.Pz() / p4.Vect().Mag();
452 const double Enumin = 0.1;
453 const int nEnubinsPerDecade = 10;
454 const int nEnubins = 31;
457 const double Emumin = 0.1;
458 const int nEmubinsPerDecade = 10;
459 const int nEmubins = 31;
462 const double costheta_min = -1;
463 const double costheta_max = +1;
464 const int ncostheta = 20;
467 double costhetabinwidth = ((costheta_max-costheta_min)/ncostheta);
468 double CosThetaBinEdges[ncostheta+1];
469 for (
int i=0; i<=ncostheta; i++)
471 CosThetaBinEdges[i] = costheta_min + i*costhetabinwidth;
475 Double_t MinLogEnu = log(Enumin);
476 Double_t MaxLogEnu = log(10*Enumin);
477 Double_t LogBinWidthEnu = ((MaxLogEnu-MinLogEnu)/nEnubinsPerDecade);
478 Double_t EnuBinEdges[nEnubins+1];
479 for (
int i=0; i<=nEnubins; i++)
481 EnuBinEdges[i] = exp(MinLogEnu + i*LogBinWidthEnu);
485 Double_t MinLogEmu = log(Emumin);
486 Double_t MaxLogEmu = log(10*Emumin);
487 Double_t LogBinWidthEmu = ((MaxLogEmu-MinLogEmu)/nEmubinsPerDecade);
488 Double_t EmuBinEdges[nEmubins+2];
489 for (
int i=0; i<=nEmubins+1; i++)
491 EmuBinEdges[i] = exp(MinLogEmu + i*LogBinWidthEmu);
495 TH3D *h3 =
new TH3D(
"h3",
"",nEmubins+1,EmuBinEdges,nEnubins,EnuBinEdges,ncostheta,CosThetaBinEdges);
501 for (
int i=1; i< h3->GetNbinsX(); i++)
503 double Emu = h3->GetXaxis()->GetBinCenter(i);
504 for (
int j=1; j<= h3->GetNbinsY(); j++)
506 double Enu = h3->GetBinCenter(j);
508 for (
int k=1; k<= h3->GetNbinsZ(); k++)
510 h3->SetBinContent(i,j,k,Int);
518 TH1D *
GetEmuPdf(
double Enu,
double costheta,
const TH3D* pdf3d)
521 int Emu_nbins = pdf3d->GetXaxis()->GetNbins();
522 const double * Emu_bins = pdf3d->GetXaxis()->GetXbins()->GetArray();
523 TH1D * pdf_Emu =
new TH1D(
"pdf_Emu",
"",Emu_nbins,Emu_bins);
524 pdf_Emu->SetDirectory(0);
527 int Enu_bin = pdf3d->GetYaxis()->FindBin(Enu);
528 int costheta_bin = pdf3d->GetZaxis()->FindBin(costheta);
531 for (
int Emu_bin = 1; Emu_bin < pdf_Emu->GetNbinsX(); Emu_bin++) {
532 pdf_Emu->SetBinContent(Emu_bin, pdf3d->GetBinContent(Emu_bin,Enu_bin,costheta_bin));
543 double dxsec_dxdy = 0;
553 AlgId id(
"genie::QPMDISPXSec",
"Default");
561 double ymax = 1 - Emu/Enu;
568 for (
int i = 0; i<=10; i++){
570 for (
int j = 0; j<=10; j++){
599 #ifdef __GENIE_FLUX_DRIVERS_ENABLED__
605 atmo_flux_driver =
dynamic_cast<GAtmoFlux *
>(fluka_flux);
609 atmo_flux_driver =
dynamic_cast<GAtmoFlux *
>(bartol_flux);
621 map<int,string>::const_iterator file_iter =
gOptFluxFiles.begin();
623 int neutrino_code = file_iter->first;
624 string filename = file_iter->second;
625 atmo_flux_driver->
AddFluxFile(neutrino_code, filename);
631 flux_driver =
dynamic_cast<GFluxI *
>(atmo_flux_driver);
634 LOG(
"gevgen_upmu",
pFATAL) <<
"You need to enable the GENIE flux drivers first!";
635 LOG(
"gevgen_upmu",
pFATAL) <<
"Use --enable-flux-drivers at the configuration step.";
647 LOG(
"gevgen_upmu",
pINFO) <<
"Parsing command line arguments";
657 bool help = parser.OptionExists(
'h');
666 if( parser.OptionExists(
'r') ) {
667 LOG(
"gevgen_upmu",
pDEBUG) <<
"Reading MC run number";
670 LOG(
"gevgen_upmu",
pDEBUG) <<
"Unspecified run number - Using default";
679 bool have_required_statistics =
false;
680 if( parser.OptionExists(
'n') ) {
682 <<
"Reading number of events to generate";
683 gOptNev = parser.ArgAsInt(
'n');
684 have_required_statistics =
true;
686 if(!have_required_statistics) {
688 <<
"You must request exposure either in terms of number of events"
689 <<
"\nUse the -n option";
699 if( parser.OptionExists(
'd') ) {
701 <<
"Reading detector side length";
705 <<
"Unspecified detector side length - Using default";
716 if( parser.OptionExists(
'f') ) {
717 LOG(
"gevgen_upmu",
pDEBUG) <<
"Getting input flux files";
718 string flux = parser.ArgAsString(
'f');
722 string::size_type jsimend = flux.find_first_of(
":",0);
723 if(jsimend==string::npos) {
725 <<
"You need to specify the flux file source";
731 for(string::size_type i=0; i<
gOptFluxSim.size(); i++) {
736 <<
"The flux file source needs to be one of <FLUKA,BGLRS>";
742 flux.erase(0,jsimend+1);
744 vector<string>::const_iterator fluxiter = fluxv.begin();
745 for( ; fluxiter != fluxv.end(); ++fluxiter) {
746 string filename_and_pdg = *fluxiter;
747 string::size_type open_bracket = filename_and_pdg.find(
"[");
748 string::size_type close_bracket = filename_and_pdg.find(
"]");
749 if (open_bracket ==string::npos ||
750 close_bracket==string::npos)
753 <<
"You made an error in specifying the flux info";
758 string::size_type ibeg = 0;
759 string::size_type iend = open_bracket;
760 string::size_type jbeg = open_bracket+1;
761 string::size_type jend = close_bracket;
762 string flux_filename = filename_and_pdg.substr(ibeg,iend-ibeg);
763 string neutrino_pdg = filename_and_pdg.substr(jbeg,jend-jbeg);
765 map<int,string>::value_type(atoi(neutrino_pdg.c_str()), flux_filename));
769 <<
"You must specify at least one flux file!";
776 LOG(
"gevgen_upmu",
pFATAL) <<
"No flux info was specified! Use the -f option.";
785 if( parser.OptionExists(
"seed") ) {
786 LOG(
"gevgen_upmu",
pINFO) <<
"Reading random number seed";
789 LOG(
"gevgen_upmu",
pINFO) <<
"Unspecified random number seed - Using default";
796 if( parser.OptionExists(
"cross-sections") ) {
797 LOG(
"gevgen_upmu",
pINFO) <<
"Reading cross-section file";
800 LOG(
"gevgen_upmu",
pINFO) <<
"Unspecified cross-section file";
811 ostringstream fluxinfo;
812 fluxinfo <<
"Using " <<
gOptFluxSim <<
" flux files: ";
813 map<int,string>::const_iterator file_iter =
gOptFluxFiles.begin();
815 int neutrino_code = file_iter->first;
816 string filename = file_iter->second;
817 TParticlePDG * p = pdglib->
Find(neutrino_code);
819 string name = p->GetName();
820 fluxinfo <<
"(" << name <<
") -> " << filename <<
" / ";
824 ostringstream expinfo;
837 <<
"\n\t" << fluxinfo.str()
839 <<
"\n\t" << expinfo.str()
847 <<
"\n gevgen_upmu [-h]"
849 <<
"\n -f simulation:flux_file[neutrino_code],..."
850 <<
"\n -n n_of_events,"
851 <<
"\n [-d detector side length (mm)]"
852 <<
"\n [--seed random_number_seed]"
853 <<
"\n --cross-sections xml_file"
854 <<
"\n [--message-thresholds xml_file]"
856 <<
" Please also read the detailed documentation at http://www.genie-mc.org"
Cross Section Calculation Interface.
void RandGen(long int seed)
double ProbabilityEmu(int nu_code, double Enu, double Emu)
void XSecTable(string inpfile, bool require_table)
static constexpr double rad
map< int, string > gOptFluxFiles
static const double kNucleonMass
double Q2(const Interaction *const i)
void GenerateUpNu(GFluxI *flux_driver)
static RandomGen * Instance()
Access instance.
void SetQ2(double Q2, bool selected=false)
Kinematics * KinePtr(void) const
void ReadFromCommandLine(int argc, char **argv)
double GetCrossSection(int nu_code, double Enu, double Emu)
double kDefOptDetectorSide
Algorithm abstract base class.
void SetRadii(double Rlongitudinal, double Rtransverse)
A singleton holding random number generator classes. All random number generation in GENIE should tak...
virtual void GenerateWeighted(bool gen_weighted)
set whether to generate weighted or unweighted neutrinos
int main(int argc, char **argv)
GAtmoFlux * GetFlux(void)
double W(const Interaction *const i)
TH1D * GetEmuPdf(double Enu, double costheta, const TH3D *pdf3d)
Summary information for an interaction.
A flux driver for the FLUKA 3-D Atmospheric Neutrino Flux.
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE...
static constexpr double cm2
void XYtoWQ2(double Ev, double M, double &W, double &Q2, double x, double y)
Algorithm * AdoptAlgorithm(const AlgId &algid) const
void BuildTune()
build tune and inform XSecSplineList
virtual double XSec(const Interaction *i, KinePhaseSpace_t k=kPSfE) const =0
Compute the cross section for the input interaction.
virtual bool GenerateNext(void)=0
generate the next flux neutrino (return false in err)
void Setx(double x, bool selected=false)
Algorithm ID (algorithm name + configuration set name)
TH3D * BuildEmuEnuCosThetaPdf(int nu_code)
void SetW(double W, bool selected=false)
static PDGLibrary * Instance(void)
static RunOpt * Instance(void)
vector< string > Split(string input, string delim)
static AlgFactory * Instance()
Singleton class to load & serve a TDatabasePDG.
void Sety(double y, bool selected=false)
static Interaction * DISCC(int tgt, int nuc, int probe, double E=0)
void AddFluxFile(int neutrino_pdg, string filename)
virtual int PdgCode(void)=0
returns the flux neutrino pdg code
virtual const TLorentzVector & Momentum(void)=0
returns the flux neutrino 4-momentum
virtual double Weight(void)=0
returns the flux neutrino weight (if any)
string PrintFramedMesg(string mesg, unsigned int nl=1, const char f='*')
void MesgThresholds(string inpfile)
TParticlePDG * Find(int pdgc, bool must_exist=true)
Command line argument parser.
void GetCommandLineArgs(int argc, char **argv)
The GENIE Algorithm Factory.
TRandom3 & RndFlux(void) const
rnd number generator used by flux drivers
A base class for the FLUKA, BGLRS and ATMNC atmo. nu. flux drivers. The driver depends on data files ...
A flux driver for the Bartol Atmospheric Neutrino Flux.
Most commonly used PDG codes. A set of utility functions to handle PDG codes is provided in PDGUtils...
TVector3 GetDetectorVertex(double CosTheta, double Enu)
GENIE Interface for user-defined flux classes.