30 #include "art_root_io/TFileService.h" 33 #include "cetlib_except/exception.h" 36 #include "nurandom/RandomUtils/NuRandomService.h" 47 #include "TDatabasePDG.h" 54 #include "CLHEP/Random/RandFlat.h" 55 #include "CLHEP/Random/RandGaussQ.h" 87 std::vector<double>
GetBinning(
const TAxis* axis,
bool finalEdge=
true);
167 ,
fMode {pset.get<
int >(
"ParticleSelectionMode")}
169 ,
fPDG {pset.get< std::vector<int> >(
"PDG")}
170 ,
fCharge {pset.get<
int >(
"Charge")}
172 ,
fEmin {pset.get<
double >(
"Emin")}
173 ,
fEmax {pset.get<
double >(
"Emax")}
174 ,
fEmid {pset.get<
double >(
"Emid")}
175 ,
fEBinsLow {pset.get<
int >(
"EBinsLow")}
177 ,
fThetamin {pset.get<
double >(
"Thetamin")}
178 ,
fThetamax {pset.get<
double >(
"Thetamax")}
181 ,
fYInput {pset.get<
double >(
"YInput")}
183 ,
fT0 {pset.get<
double >(
"T0")}
184 ,
fSigmaT {pset.get<
double >(
"SigmaT")}
185 ,
fTDist {pset.get<
int >(
"TDist")}
186 ,
fSetParam {pset.get<
bool >(
"SetParam")}
187 ,
fSetRead {pset.get<
bool >(
"SetRead")}
188 ,
fSetWrite {pset.get<
bool >(
"SetWrite")}
190 ,
fEpsilon {pset.get<
double >(
"Epsilon")}
192 produces< std::vector<simb::MCTruth> >();
193 produces< sumdata::RunData, art::InRun >();
201 for (
unsigned int i=0; i < geom->
Ncryostats() ; i++ ) {
229 fTree = tfs->make<TTree>(
"Generator",
"analysis tree");
241 fTree->Branch(
"Phi" ,&
Phi ,
"Phi/D" );
248 if (
fThetamax >
M_PI/2 + 0.01 )
throw cet::exception(
"GaisserParam")<<
"\nThetamax has to be less than " <<
M_PI/2 <<
", but was entered as " <<
fThetamax <<
", this cause an error so leaving program now...\n\n";
262 std::unique_ptr< std::vector<simb::MCTruth> > truthcol(
new std::vector<simb::MCTruth>);
271 truthcol->push_back(truth);
281 CLHEP::RandFlat
flat(engine);
282 CLHEP::RandGaussQ
gauss(engine);
291 int trackid = -1*(i+1);
298 if(1.0-2.0*flat.fire() > 0)
fPDG[i]=-
fPDG[i];
302 static TDatabasePDG pdgt;
303 TParticlePDG* pdgp = pdgt.GetParticle(
fPDG[i]);
304 if (pdgp) m = pdgp->Mass();
320 TLorentzVector
pos(x[0], x[1], x[2],
Time);
326 std::pair<double,double> theta_energy;
330 Theta = theta_energy.first;
331 Phi =
M_PI*( 1.0-2.0*flat.fire() );
335 Gamma = 1 + (KinEnergy/
m);
340 pmom[1] = -
Momentum*std::cos(Theta);
343 pnorm = std::sqrt( pmom[0]*pmom[0] + pmom[1]*pmom[1] + pmom[2]*pmom[2] );
349 std::cout <<
"MuFlux map hasn't been initialised, aborting...." <<
std::endl;
353 TLorentzVector pvec(pmom[0], pmom[1], pmom[2],
Energy );
379 std::cout <<
"x: " << pos.X() <<
" y: " << pos.Y() <<
" z: " << pos.Z() <<
" time: " << pos.T() <<
std::endl;
380 std::cout <<
"Px: " << pvec.Px() <<
" Py: " << pvec.Py() <<
" Pz: " << pvec.Pz() <<
std::endl;
393 for (
unsigned int i=0; i<
fPDG.size(); ++i) {
400 CLHEP::RandFlat
flat(engine);
402 unsigned int i=flat.fireInt(
fPDG.size());
407 mf::LogWarning(
"UnrecognizeOption") <<
"GaisserParam does not recognize ParticleSelectionMode " 418 if(rand1 < 0 || rand1 > 1) std::cerr <<
"GetThetaAndEnergy:\tInvalid random number " << rand1 <<
std::endl;
419 if(rand2 < 0 || rand2 > 1) std::cerr <<
"GetThetaAndEnergy:\tInvalid random number " << rand2 <<
std::endl;
423 if(
m_thetaHist->GetBinContent(thetaBin) < rand1) thetaBin += 1;
425 double thetaLow =
m_thetaHist->GetXaxis()->GetBinLowEdge(thetaBin);
426 double thetaUp =
m_thetaHist->GetXaxis()->GetBinUpEdge(thetaBin);
427 double theta = drand1*(thetaUp-thetaLow) + thetaLow;
431 bool notFound =
true;
433 if( fabs(mapit->first+thetaLow)<0.000001 ) {
434 energyHist = mapit->second;
439 if(notFound) std::cout <<
"GetThetaAndEnergy: ERROR:\tInvalid theta!" <<
std::endl;
442 energyHist->GetBinWithContent(
double(rand2),energyBin,1,energyHist->GetNbinsX(),1.0);
443 if(energyHist->GetBinContent(energyBin) < rand2) energyBin += 1;
444 double drand2 = (energyHist->GetBinContent(energyBin) - rand2)/(energyHist->GetBinContent(energyBin) - energyHist->GetBinContent(energyBin-1));
445 double energyLow = energyHist->GetXaxis()->GetBinLowEdge(energyBin);
446 double energyUp = energyHist->GetXaxis()->GetBinUpEdge(energyBin);
447 double energy = drand2*(energyUp-energyLow) + energyLow;
450 return std::make_pair(theta,energy);
456 std::cout <<
"In my function MakePDF" <<
std::endl;
460 double TotalMuonFlux=0;
465 std::cout <<
"MakePDF: Map has already been initialised. " <<
std::endl;
466 std::cout <<
"Do fSetReWrite - true if you really want to override this map." <<
std::endl;
474 std::cout <<
"Making new dhist_Map called m_PDFmap....." <<
std::endl;
477 TF2* muonSpec =
new TF2(
"muonSpec",
this,
480 "GaisserParam",
"GaisserMuonFlux_Integrand" 487 std::cout <<
"Surface flux of muons = " << TotalMuonFlux <<
" cm-2 s-1" <<
std::endl;
490 std::ostringstream pdfFile;
493 std::replace(tmpfileName.begin(),tmpfileName.end(),
'+',
'0');
494 if (tmpfileName ==
"GaisserPDF_0-100-100100-1000-10000-0-1.5708-100.root") tmpfileName =
"GaisserPDF_DefaultBins.root";
495 else if (tmpfileName ==
"GaisserPDF_0-100-4000-1000-1000-0-1.5708-100.root") tmpfileName =
"GaisserPDF_LowEnergy.root";
496 else if (tmpfileName ==
"GaisserPDF_4000-10000-100000-1000-10000-0-1.5708-100.root") tmpfileName =
"GaisserPDF_MidEnergy.root";
497 else if (tmpfileName ==
"GaisserPDF_100000-500000-1e007-10000-100000-0-1.5708-100.root") tmpfileName =
"GaisserPDF_HighEnergy.root";
499 std::ostringstream pdfFilePath;
508 if( sp.
find_file(tmpfileName, fROOTfile) ) fileName = fROOTfile;
510 std::cout <<
"File path; " << fileName <<
std::endl;
515 if(!fSetRead) std::cout <<
"WARNING- "+fileName+
" does not exist." <<
std::endl;
517 std::cout <<
"Reading PDF from file "+fileName <<
std::endl;
518 m_File =
new TFile(fileName.c_str());
519 if(
m_File->IsZombie() ||
m_File->TestBit(TFile::kRecovered)){
520 std::cout <<
"WARNING- "+fileName+
" is corrupted or cannot be read." <<
std::endl;
527 std::cout <<
"Now going to read file...." <<
std::endl;
532 std::ostringstream pdfEnergyHist;
533 pdfEnergyHist <<
"pdf_energy_"<<i;
534 std::string pdfEnergyHiststr = pdfEnergyHist.str();
536 TH1* pdf_hist = (TH1D*)
m_File->Get( pdfEnergyHiststr.c_str() );
537 m_PDFmap->insert(std::make_pair(-thetalow,pdf_hist));
538 thetalow = double(i)*(
fThetamax)/
double(fThetaBins);
543 std::cout <<
"Generating a new muon flux PDF" <<
std::endl;
545 std::cout <<
"Writing to PDF to file "+fileName <<
std::endl;
546 m_File =
new TFile(fileName.c_str(),
"RECREATE");
549 double dnbins_theta = double(fThetaBins);
552 double di = i==0 ? 0.1 : double(i);
555 m_thetaHist->SetBinContent(i, int_i/TotalMuonFlux);
558 std::cout <<
"theta PDF complete... now making the energy PDFs (this will take a little longer)... " <<
std::endl;
564 double di = double(i);
572 TH1* pdf_lowenergy =
new TH1D(
"pdf_lowenergy",
"pdf_lowenergy", nbins,
fEmin,
fEmid);
573 double dnbins = double(nbins);
574 for(
int j=1; j<=
nbins; j++){
575 double dj = double(j);
579 pdf_lowenergy->SetBinContent(j, int_j/int_tot);
584 dnbins=double(nbins);
585 TH1* pdf_highenergy =
new TH1D(
"pdf_highenergy",
"pdf_highenergy", nbins,
fEmid,
fEmax);
586 for(
int j=1; j<=
nbins; j++){
587 double dj = double(j);
590 pdf_highenergy->SetBinContent(j, int_j/int_tot);
594 std::vector<double> vxbins =
GetBinning(pdf_lowenergy->GetXaxis(),
false);
595 std::vector<double> vxbins2 =
GetBinning(pdf_highenergy->GetXaxis());
596 vxbins.insert(vxbins.end(), vxbins2.begin(), vxbins2.end());
599 double* xbins =
new double[vxbins.size()];
601 TH1* pdf_energy =
new TH1D(
"pdf_energy",
"pdf_energy", vxbins.size()-1, xbins);
603 for(ibin = 1; ibin<=pdf_lowenergy->GetNbinsX(); ibin++, ibin2++){
604 double content = pdf_lowenergy->GetBinContent(ibin);
605 if(ibin == 1) content = content - 0.00001;
606 pdf_energy->Fill(pdf_energy->GetBinCenter(ibin2), content);
608 for(ibin = 1; ibin<=pdf_highenergy->GetNbinsX(); ibin++, ibin2++){
609 pdf_energy->Fill(pdf_energy->GetBinCenter(ibin2), pdf_highenergy->GetBinContent(ibin));
613 std::ostringstream Clonestr;
614 Clonestr <<
"pdf_energy_"<<i;
615 TH1* pdf_energy_noneg = (TH1D*) pdf_energy->Clone( Clonestr.str().c_str() );
616 pdf_energy_noneg->Reset();
621 for(ibin = 1; ibin<=pdf_energy->GetNbinsX(); ibin++){
622 double newPD = pdf_energy->GetBinContent(ibin);
623 double probDiff = newPD - lastPD;
625 if(ibin!=pdf_energy->GetNbinsX()){
631 else PDF += probDiff;
633 for(
int iskip=0; iskip <= nSkip; iskip++) pdf_energy_noneg->Fill(pdf_energy_noneg->GetBinCenter(ibin-iskip),
PDF);
641 m_PDFmap->insert(std::make_pair(-thetalow,pdf_energy_noneg));
647 delete pdf_lowenergy;
648 delete pdf_highenergy;
651 std::cout <<
"\r===> " << 100.0*double(i)/double(fThetaBins) <<
"% complete... " <<
std::endl;
653 std::cout <<
"finished the energy pdfs." <<
std::endl;
663 double ct = cos(theta);
671 double c1 = sqrt(1.-(1.-
pow(ct,2.0))/
pow( (1.+32./6370.) ,2.0));
672 double deltae = 2.06e-3 * (1030. / c1 - 120.);
673 double em = e + deltae/2.;
674 double e1 = e + deltae;
675 double pdec =
pow( (120. / (1030. / c1)), (1.04 / c1 / em));
676 di=A*
pow(e1,-gamma)*(1./(1.+1.1*e1*c1/115.) + 0.054/(1.+1.1*e1*c1/850.) +
rc)*pdec;
682 double gamma2 = 1.29;
683 double ct_star = sqrt( (
pow(ct,2) + 0.102573*0.102573 - 0.068287*
pow(ct,0.958633)
684 + 0.0407253*
pow(ct,0.817285) )/(1.0 + 0.102573*0.102573 - 0.068287 + 0.0407253) );
685 double eMod = e*(1.0+C/(e*
pow(ct_star,gamma2)));
686 di=A*
pow(eMod,-gamma)*(1./(1.+1.1*e*ct_star/115.) + 0.054/(1.+1.1*e*ct_star/850.));
703 std::vector<double> vbins;
704 for(
int ibin=1; ibin<=axis->GetNbins()+1; ibin++){
705 if(ibin<=axis->GetNbins()) vbins.push_back(axis->GetBinLowEdge(ibin));
706 else if(finalEdge) vbins.push_back(axis->GetBinLowEdge(ibin) + axis->GetBinWidth(ibin));
716 if(mapit->second)
delete mapit->second;
720 std::cout <<
"Reset PDFmap and thetaHist..." <<
std::endl;
double fEpsilon
Minimum integration sum....
void AddTrajectoryPoint(TLorentzVector const &position, TLorentzVector const &momentum)
double fThetamax
Maximum theta.
void SetOrigin(simb::Origin_t origin)
static constexpr int kGAUS
module to produce single or multiple specified particles in the detector
double fYInput
Max Y position.
int fThetaBins
Number of theta Bins.
EDProducer(fhicl::ParameterSet const &pset)
double fEmid
Energy to go from low to high (GeV)
bool fSetReWrite
Whether to ReWrite pdfs.
double GaisserFlux(double e, double theta)
void produce(art::Event &evt) override
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
CLHEP::HepRandomEngine & fEngine
art-managed random-number engine
std::string fInputDir
Input Directory.
void CryostatBoundaries(double *boundaries, geo::CryostatID const &cid) const
Returns the boundaries of the specified cryostat.
art framework interface to geometry description
int fEBinsLow
Number of low energy Bins.
GaisserParam(fhicl::ParameterSet const &pset)
static QChar PDF((ushort) 0x202c)
#define DEFINE_ART_MODULE(klass)
std::map< double, TH1 * > dhist_Map
std::string DetectorName() const
Returns a string with the name of the detector, as configured.
single particles thrown at the detector
double fEmin
Minimum Kinetic Energy (GeV)
double fSigmaT
Variation in t position (ns)
ProductID put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
void Sample(simb::MCTruth &mct, CLHEP::HepRandomEngine &engine)
std::vector< double > GetBinning(const TAxis *axis, bool finalEdge=true)
bool fSetParam
Which version of Gaissers Param.
double gamma(double KE, const simb::MCParticle *part)
double fEmax
Maximum Kinetic Energy (GeV)
double fXHalfRange
Max X position.
double fCryoBoundaries[6]
void Add(simb::MCParticle const &part)
int fEBinsHigh
Number of high energy Bins.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::string find_file(std::string const &filename) const
std::vector< int > fPDG
PDG code of particles to generate.
void SampleOne(unsigned int i, simb::MCTruth &mct, CLHEP::HepRandomEngine &engine)
bool fSetRead
Whether to Read.
double fThetamin
Minimum theta.
double GaisserMuonFlux_Integrand(Double_t *x, Double_t *par)
int fTDist
How to distribute t (gaus, or uniform)
Event generator information.
double fT0
Central t position (ns) in world coordinates.
std::map< double, TH1 * >::iterator dhist_Map_it
LArSoft geometry interface.
std::pair< double, double > GetThetaAndEnergy(double rand1, double rand2)
void beginRun(art::Run &run) override
Event Generation using GENIE, cosmics or single particles.
bool fSetWrite
Whether to Write.
cet::coded_exception< error, detail::translate > exception
QTextStream & endl(QTextStream &s)
double fZHalfRange
Max Z position.