31 #include "art_root_io/TFileService.h" 32 #include "cetlib_except/exception.h" 48 #include "TDatabasePDG.h" 55 #include "CLHEP/Random/RandFlat.h" 56 #include "CLHEP/Random/RandGaussQ.h" 87 std::vector<double>
GetBinning(
const TAxis* axis,
bool finalEdge =
true);
97 std::vector<int>
fPDG;
154 ,
fMode{pset.get<
int>(
"ParticleSelectionMode")}
156 ,
fPDG{pset.get<std::vector<int>>(
"PDG")}
157 ,
fCharge{pset.get<
int>(
"Charge")}
158 ,
fInputDir{pset.get<std::string>(
"InputDir")}
159 ,
fEmin{pset.get<
double>(
"Emin")}
160 ,
fEmax{pset.get<
double>(
"Emax")}
161 ,
fEmid{pset.get<
double>(
"Emid")}
164 ,
fThetamin{pset.get<
double>(
"Thetamin")}
165 ,
fThetamax{pset.get<
double>(
"Thetamax")}
168 ,
fYInput{pset.get<
double>(
"YInput")}
170 ,
fT0{pset.get<
double>(
"T0")}
171 ,
fSigmaT{pset.get<
double>(
"SigmaT")}
172 ,
fTDist{pset.get<
int>(
"TDist")}
174 ,
fSetRead{pset.get<
bool>(
"SetRead")}
177 ,
fEpsilon{pset.get<
double>(
"Epsilon")}
179 produces<std::vector<simb::MCTruth>>();
180 produces<sumdata::RunData, art::InRun>();
200 fTree = tfs->make<TTree>(
"Generator",
"analysis tree");
212 fTree->Branch(
"Phi", &
Phi,
"Phi/D");
221 <<
"\nThetamax has to be less than " << M_PI / 2 <<
", but was entered as " <<
fThetamax 222 <<
", this cause an error so leaving program now...\n\n";
225 <<
"\nThetamin has to be more than 0, but was entered as " <<
fThetamin 226 <<
", this cause an error so leaving program now...\n\n" 230 <<
"\nMinimum angle is bigger than maximum angle....causes an error so leaving program " 244 std::unique_ptr<std::vector<simb::MCTruth>> truthcol(
new std::vector<simb::MCTruth>);
253 truthcol->push_back(truth);
255 evt.
put(std::move(truthcol));
264 CLHEP::RandFlat flat(engine);
265 CLHEP::RandGaussQ gauss(engine);
274 int trackid = -1 * (i + 1);
275 std::string primary(
"primary");
281 if (1.0 - 2.0 * flat.fire() > 0)
fPDG[i] = -
fPDG[i];
287 static TDatabasePDG pdgt;
288 TParticlePDG* pdgp = pdgt.GetParticle(
fPDG[i]);
289 if (pdgp) m = pdgp->Mass();
303 TLorentzVector pos(x[0], x[1], x[2],
Time);
309 std::pair<double, double> theta_energy;
313 Theta = theta_energy.first;
314 Phi = M_PI * (1.0 - 2.0 * flat.fire());
318 Gamma = 1 + (KinEnergy / m);
322 pmom[0] =
Momentum * std::sin(Theta) * std::cos(
Phi);
323 pmom[1] = -
Momentum * std::cos(Theta);
324 pmom[2] =
Momentum * std::sin(Theta) * std::sin(
Phi);
326 pnorm = std::sqrt(pmom[0] * pmom[0] + pmom[1] * pmom[1] + pmom[2] * pmom[2]);
332 std::cout <<
"MuFlux map hasn't been initialised, aborting...." << std::endl;
336 TLorentzVector pvec(pmom[0], pmom[1], pmom[2],
Energy);
344 std::cout <<
"Theta: " <<
Theta <<
" Phi: " <<
Phi <<
" KineticEnergy: " <<
KinEnergy 345 <<
" Energy: " <<
Energy <<
" Momentum: " <<
Momentum << std::endl;
346 std::cout <<
"x: " << pos.X() <<
" y: " << pos.Y() <<
" z: " << pos.Z() <<
" time: " << pos.T()
348 std::cout <<
"Px: " << pvec.Px() <<
" Py: " << pvec.Py() <<
" Pz: " << pvec.Pz() << std::endl;
362 for (
unsigned int i = 0; i <
fPDG.size(); ++i) {
369 CLHEP::RandFlat flat(engine);
371 unsigned int i = flat.fireInt(
fPDG.size());
376 <<
"GaisserParam does not recognize ParticleSelectionMode " <<
fMode;
386 if (rand1 < 0 || rand1 > 1)
387 std::cerr <<
"GetThetaAndEnergy:\tInvalid random number " << rand1 << std::endl;
388 if (rand2 < 0 || rand2 > 1)
389 std::cerr <<
"GetThetaAndEnergy:\tInvalid random number " << rand2 << std::endl;
393 if (
m_thetaHist->GetBinContent(thetaBin) < rand1) thetaBin += 1;
397 double thetaLow =
m_thetaHist->GetXaxis()->GetBinLowEdge(thetaBin);
398 double thetaUp =
m_thetaHist->GetXaxis()->GetBinUpEdge(thetaBin);
399 double theta = drand1 * (thetaUp - thetaLow) + thetaLow;
403 bool notFound =
true;
405 if (fabs(mapit->first + thetaLow) < 0.000001) {
406 energyHist = mapit->second;
411 if (notFound) std::cout <<
"GetThetaAndEnergy: ERROR:\tInvalid theta!" << std::endl;
414 energyHist->GetBinWithContent(
double(rand2), energyBin, 1, energyHist->GetNbinsX(), 1.0);
415 if (energyHist->GetBinContent(energyBin) < rand2) energyBin += 1;
417 (energyHist->GetBinContent(energyBin) - rand2) /
418 (energyHist->GetBinContent(energyBin) - energyHist->GetBinContent(energyBin - 1));
419 double energyLow = energyHist->GetXaxis()->GetBinLowEdge(energyBin);
420 double energyUp = energyHist->GetXaxis()->GetBinUpEdge(energyBin);
421 double energy = drand2 * (energyUp - energyLow) + energyLow;
424 return std::make_pair(theta, energy);
430 std::cout <<
"In my function MakePDF" << std::endl;
434 double TotalMuonFlux = 0;
437 std::cout <<
"PDFMAP" << std::endl;
439 std::cout <<
"MakePDF: Map has already been initialised. " << std::endl;
440 std::cout <<
"Do fSetReWrite - true if you really want to override this map." << std::endl;
448 std::cout <<
"Making new dhist_Map called m_PDFmap....." << std::endl;
451 TF2* muonSpec =
new TF2(
"muonSpec",
460 "GaisserMuonFlux_Integrand");
465 TotalMuonFlux = muonSpec->Integral(
467 std::cout <<
"Surface flux of muons = " << TotalMuonFlux <<
" cm-2 s-1" << std::endl;
470 std::ostringstream pdfFile;
473 std::string tmpfileName = pdfFile.str();
474 std::replace(tmpfileName.begin(), tmpfileName.end(),
'+',
'0');
475 if (tmpfileName ==
"GaisserPDF_0-100-100100-1000-10000-0-1.5708-100.root")
476 tmpfileName =
"GaisserPDF_DefaultBins.root";
477 else if (tmpfileName ==
"GaisserPDF_0-100-4000-1000-1000-0-1.5708-100.root")
478 tmpfileName =
"GaisserPDF_LowEnergy.root";
479 else if (tmpfileName ==
"GaisserPDF_4000-10000-100000-1000-10000-0-1.5708-100.root")
480 tmpfileName =
"GaisserPDF_MidEnergy.root";
481 else if (tmpfileName ==
"GaisserPDF_100000-500000-1e007-10000-100000-0-1.5708-100.root")
482 tmpfileName =
"GaisserPDF_HighEnergy.root";
484 std::ostringstream pdfFilePath;
486 std::string fileName = pdfFilePath.str();
488 cet::search_path sp(
"FW_SEARCH_PATH");
489 std::string fROOTfile;
490 if (sp.find_file(tmpfileName, fROOTfile)) fileName = fROOTfile;
492 std::cout <<
"File path; " << fileName << std::endl;
496 fSetRead = stat(fileName.c_str(), &buffer) == 0;
498 std::cout <<
"WARNING- " + fileName +
" does not exist." << std::endl;
500 std::cout <<
"Reading PDF from file " + fileName << std::endl;
501 m_File =
new TFile(fileName.c_str());
503 m_File->TestBit(TFile::kRecovered)) {
504 std::cout <<
"WARNING- " + fileName +
" is corrupted or cannot be read." << std::endl;
511 std::cout <<
"Now going to read file...." << std::endl;
516 std::ostringstream pdfEnergyHist;
517 pdfEnergyHist <<
"pdf_energy_" << i;
518 std::string pdfEnergyHiststr = pdfEnergyHist.str();
520 TH1* pdf_hist = (TH1D*)
m_File->Get(pdfEnergyHiststr.c_str());
521 m_PDFmap->insert(std::make_pair(-thetalow, pdf_hist));
522 thetalow = double(i) * (
fThetamax) /
double(fThetaBins);
527 std::cout <<
"Generating a new muon flux PDF" << std::endl;
529 std::cout <<
"Writing to PDF to file " + fileName << std::endl;
530 m_File =
new TFile(fileName.c_str(),
"RECREATE");
533 double dnbins_theta = double(fThetaBins);
536 double di = i == 0 ? 0.1 : double(i);
537 double theta = di * (
fThetamax) / dnbins_theta;
539 m_thetaHist->SetBinContent(i, int_i / TotalMuonFlux);
543 <<
"theta PDF complete... now making the energy PDFs (this will take a little longer)... " 550 double di = double(i);
551 double theta = di * (
fThetamax) / fThetaBins;
558 TH1* pdf_lowenergy =
new TH1D(
"pdf_lowenergy",
"pdf_lowenergy", nbins,
fEmin,
fEmid);
559 double dnbins = double(nbins);
560 for (
int j = 1; j <= nbins; j++) {
561 double dj = double(j);
562 double int_j = muonSpec->Integral(
564 pdf_lowenergy->SetBinContent(j, int_j / int_tot);
569 dnbins = double(nbins);
570 TH1* pdf_highenergy =
new TH1D(
"pdf_highenergy",
"pdf_highenergy", nbins,
fEmid,
fEmax);
571 for (
int j = 1; j <= nbins; j++) {
572 double dj = double(j);
573 double int_j = muonSpec->Integral(
575 pdf_highenergy->SetBinContent(j, int_j / int_tot);
579 std::vector<double> vxbins =
GetBinning(pdf_lowenergy->GetXaxis(),
false);
580 std::vector<double> vxbins2 =
GetBinning(pdf_highenergy->GetXaxis());
581 vxbins.insert(vxbins.end(), vxbins2.begin(), vxbins2.end());
584 double* xbins =
new double[vxbins.size()];
587 xbins[ibin] = (*binit);
588 TH1* pdf_energy =
new TH1D(
"pdf_energy",
"pdf_energy", vxbins.size() - 1, xbins);
590 for (ibin = 1; ibin <= pdf_lowenergy->GetNbinsX(); ibin++, ibin2++) {
591 double content = pdf_lowenergy->GetBinContent(ibin);
592 if (ibin == 1) content = content - 0.00001;
593 pdf_energy->Fill(pdf_energy->GetBinCenter(ibin2), content);
595 for (ibin = 1; ibin <= pdf_highenergy->GetNbinsX(); ibin++, ibin2++) {
596 pdf_energy->Fill(pdf_energy->GetBinCenter(ibin2), pdf_highenergy->GetBinContent(ibin));
600 std::ostringstream Clonestr;
601 Clonestr <<
"pdf_energy_" << i;
602 TH1* pdf_energy_noneg = (TH1D*)pdf_energy->Clone(Clonestr.str().c_str());
603 pdf_energy_noneg->Reset();
608 for (ibin = 1; ibin <= pdf_energy->GetNbinsX(); ibin++) {
609 double newPD = pdf_energy->GetBinContent(ibin);
610 double probDiff = newPD - lastPD;
612 if (ibin != pdf_energy->GetNbinsX()) {
621 if (PDF > 1) PDF = 1;
622 for (
int iskip = 0; iskip <= nSkip; iskip++)
623 pdf_energy_noneg->Fill(pdf_energy_noneg->GetBinCenter(ibin - iskip), PDF);
629 if (
fSetWrite) pdf_energy_noneg->Write();
631 std::make_pair(-thetalow, pdf_energy_noneg));
637 delete pdf_lowenergy;
638 delete pdf_highenergy;
641 std::cout <<
"\r===> " << 100.0 * double(i) / double(fThetaBins) <<
"% complete... " 644 std::cout <<
"finished the energy pdfs." << std::endl;
655 double ct = cos(theta);
661 double c1 = sqrt(1. - (1. - pow(ct, 2.0)) / pow((1. + 32. / 6370.), 2.0));
662 double deltae = 2.06e-3 * (1030. / c1 - 120.);
663 double em = e + deltae / 2.;
664 double e1 = e + deltae;
665 double pdec = pow((120. / (1030. / c1)), (1.04 / c1 / em));
666 di = A * pow(e1, -gamma) *
667 (1. / (1. + 1.1 * e1 * c1 / 115.) + 0.054 / (1. + 1.1 * e1 * c1 / 850.) + rc) * pdec;
673 double gamma2 = 1.29;
674 double ct_star = sqrt((pow(ct, 2) + 0.102573 * 0.102573 - 0.068287 * pow(ct, 0.958633) +
675 0.0407253 * pow(ct, 0.817285)) /
676 (1.0 + 0.102573 * 0.102573 - 0.068287 + 0.0407253));
677 double eMod = e * (1.0 + C / (e * pow(ct_star, gamma2)));
678 di = A * pow(eMod, -gamma) *
679 (1. / (1. + 1.1 * e * ct_star / 115.) + 0.054 / (1. + 1.1 * e * ct_star / 850.));
690 double flux = 2.0 * M_PI * sin(x[1]) *
GaisserFlux(x[0], x[1]);
698 std::vector<double> vbins;
699 for (
int ibin = 1; ibin <= axis->GetNbins() + 1; ibin++) {
700 if (ibin <= axis->GetNbins())
701 vbins.push_back(axis->GetBinLowEdge(ibin));
703 vbins.push_back(axis->GetBinLowEdge(ibin) + axis->GetBinWidth(ibin));
714 if (mapit->second)
delete mapit->second;
718 std::cout <<
"Reset PDFmap and thetaHist..." << std::endl;
details::range_type< T > Iterate() const
Initializes the specified ID with the ID of the first cryostat.
base_engine_t & createEngine(seed_t seed)
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.
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
double GaisserFlux(double e, double theta)
void produce(art::Event &evt) override
Geometry information for a single cryostat.
CLHEP::HepRandomEngine & fEngine
art-managed random-number engine
std::string fInputDir
Input Directory.
int fEBinsLow
Number of low energy Bins.
PutHandle< PROD > put(std::unique_ptr< PROD > &&edp, std::string const &instance={})
GaisserParam(fhicl::ParameterSet const &pset)
#define DEFINE_ART_MODULE(klass)
std::map< double, TH1 * > dhist_Map
single particles thrown at the detector
double fEmin
Minimum Kinetic Energy (GeV)
double fSigmaT
Variation in t position (ns)
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.
An art service to assist in the distribution of guaranteed unique seeds to all engines within an art ...
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::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)
std::string const & DetectorName() const
Returns a string with the name of the detector, as configured.
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
Namespace collecting geometry-related classes utilities.
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.
art framework interface to geometry description
cet::coded_exception< error, detail::translate > exception
double fZHalfRange
Max Z position.