10 #include "cetlib/search_path.h" 11 #include "cetlib_except/exception.h" 22 #include "TLorentzVector.h" 25 #include "CLHEP/Random/RandFlat.h" 26 #include "CLHEP/Random/RandPoisson.h" 39 , fNumberOfStartLevels(21)
40 , fBranchingRatios(fNumberOfLevels)
41 , fDecayTo(fNumberOfLevels)
42 , fMonoenergeticNeutrinos(parameterSet.
get<bool>(
"MonoenergeticNeutrinos"))
43 , fNeutrinoEnergy(parameterSet.
get<double>(
"NeutrinoEnergy"))
44 , fEnergySpectrumFileName(parameterSet.
get<
std::string>(
"EnergySpectrumFileName"))
45 , fUsePoissonDistribution(parameterSet.
get<bool>(
"UsePoissonDistribution"))
46 , fAllowZeroNeutrinos(parameterSet.
get<bool>(
"AllowZeroNeutrinos"))
47 , fNumberOfNeutrinos(parameterSet.
get<int>(
"NumberOfNeutrinos"))
48 , fNeutrinoTimeBegin(parameterSet.
get<double>(
"NeutrinoTimeBegin"))
49 , fNeutrinoTimeEnd(parameterSet.
get<double>(
"NeutrinoTimeEnd"))
52 fActiveVolume.push_back(parameterSet.
get<std::vector<double>>(
"ActiveVolume0"));
53 fActiveVolume.push_back(parameterSet.
get<std::vector<double>>(
"ActiveVolume1"));
65 std::vector<simb::MCTruth> truths;
68 for (
int i = 0; i < NumberOfNu; ++i) {
78 truths.push_back(truth);
87 CLHEP::HepRandomEngine& engine)
const 90 CLHEP::RandFlat randFlat(engine);
92 std::vector<double> isotropicDirection;
94 double phi = 2 * TMath::Pi() * randFlat.fire();
95 double cosTheta = 2 * randFlat.fire() - 1;
96 double theta = TMath::ACos(cosTheta);
99 isotropicDirection.push_back(cos(phi) * sin(theta));
100 isotropicDirection.push_back(sin(phi) * sin(theta));
101 isotropicDirection.push_back(cosTheta);
103 return isotropicDirection;
111 CLHEP::RandFlat randFlat(engine);
113 std::vector<double> position;
128 CLHEP::RandPoisson randPoisson(engine);
142 CLHEP::RandFlat randFlat(engine);
155 CLHEP::RandFlat randFlat(engine);
157 double neutrinoEnergy = 0.0;
159 double randomNumber = randFlat.fire();
162 std::pair<double, double> previousPair;
166 ++energyProbability) {
167 if (randomNumber < energyProbability->
second) {
170 energyProbability->first - (energyProbability->second - randomNumber) *
171 (energyProbability->first - previousPair.first) /
172 (energyProbability->second - previousPair.second);
176 neutrinoEnergy = energyProbability->first;
180 previousPair = *energyProbability;
183 return neutrinoEnergy;
191 cet::search_path searchPath(
"FW_SEARCH_PATH");
194 std::string fullName;
195 searchPath.find_file(directoryName, fullName);
197 if (fullName.empty())
199 <<
"Cannot find file with neutrino energy spectrum " << fullName <<
'\n';
201 TFile energySpectrumFile(fullName.c_str(),
"READ");
203 std::string energySpectrumGraphName =
"NueSpectrum";
204 TGraph* energySpectrumGraph =
205 dynamic_cast<TGraph*
>(energySpectrumFile.Get(energySpectrumGraphName.c_str()));
207 double integral = 0.0;
208 int numberOfPoints = energySpectrumGraph->GetN();
209 double* energyValues = energySpectrumGraph->GetX();
210 double* fluxValues = energySpectrumGraph->GetY();
211 for (
int point = 0; point < numberOfPoints; ++point)
212 integral += fluxValues[point];
214 double probability = 0.0;
215 for (
int point = 0; point < numberOfPoints; ++point) {
216 probability += fluxValues[point] / integral;
767 double startEnergyLevels[] = {2.281, 2.752, 2.937, 3.143, 3.334, 3.569, 3.652,
768 3.786, 3.861, 4.067, 4.111, 4.267, 4.364, 4.522,
769 4.655, 4.825, 5.017, 5.080, 5.223, 5.696, 6.006};
774 double b[] = {0.9, 1.5, 0.11, 0.06, 0.04, 0.01, 0.16, 0.26, 0.01, 0.05, 0.11,
775 0.29, 3.84, 0.31, 0.38, 0.47, 0.36, 0.23, 0.03, 0.11, 0.13};
779 double energyLevels[] = {
780 7.4724, 6.2270, 5.06347, 4.99294, 4.8756, 4.87255, 4.78865, 4.744093, 4.53706,
781 4.47299, 4.41936, 4.39588, 4.3840, 4.3656, 4.28052, 4.25362, 4.21307, 4.18003,
782 4.14901, 4.11084, 4.10446, 4.02035, 3.92390, 3.88792, 3.86866, 3.840228, 3.82143,
783 3.79757, 3.76779, 3.73848, 3.663739, 3.62995, 3.59924, 3.55697, 3.48621, 3.439144,
784 3.41434, 3.39363, 3.36803, 3.22867, 3.15381, 3.14644, 3.12836, 3.109721, 3.1002,
785 3.02795, 2.98587, 2.9508, 2.87901, 2.80788, 2.7874, 2.786644, 2.75672, 2.74691,
786 2.730372, 2.625990, 2.57593, 2.558, 2.54277, 2.419171, 2.397165, 2.290493, 2.289871,
787 2.26040, 2.103668, 2.069809, 2.047354, 1.959068, 1.643639, 0.891398, 0.8001427, 0.0298299,
799 CLHEP::HepRandomEngine& engine)
const 802 bool success =
false;
814 double neutrinoEnergy,
816 CLHEP::HepRandomEngine& engine)
const 819 CLHEP::RandFlat randFlat(engine);
821 int highestLevel = 0;
824 double totalCrossSection = 0;
827 crossSection != levelCrossSections.end();
829 totalCrossSection += *crossSection;
831 if (totalCrossSection == 0)
return false;
833 std::vector<double> startLevelProbabilities;
836 crossSection != levelCrossSections.end();
838 startLevelProbabilities.push_back((*crossSection) / totalCrossSection);
840 double randomNumber = randFlat.fire();
842 int chosenStartLevel = -1;
844 for (
int level = 0; level < highestLevel; ++level) {
845 if (randomNumber < (startLevelProbabilities.at(level) + tprob)) {
846 chosenStartLevel = level;
849 tprob += startLevelProbabilities.at(level);
857 std::vector<double> levelDelay;
859 levelDelay.push_back(0.0);
863 int highestHigher = 0;
879 lastLevel = lowestLower;
889 lastLevel = highestHigher;
890 level = highestHigher;
907 int neutrinoTrackID = -1 * (truth.
NParticles() + 1);
908 std::string primary(
"primary");
911 double neutrinoP = neutrinoEnergy / 1000.0;
912 double neutrinoPx = neutrinoDirection.at(0) * neutrinoP;
913 double neutrinoPy = neutrinoDirection.at(1) * neutrinoP;
914 double neutrinoPz = neutrinoDirection.at(2) * neutrinoP;
922 TLorentzVector neutrinoPosition(vertex.at(0), vertex.at(1), vertex.at(2), neutrinoTime);
923 TLorentzVector neutrinoMomentum(neutrinoPx, neutrinoPy, neutrinoPz, neutrinoEnergy / 1000.0);
933 double electronEnergy = neutrinoEnergy - (
fEnergyLevels.at(lastLevel) + 1.5);
934 double electronEnergyGeV = electronEnergy / 1000.0;
936 double electronM = 0.000511;
937 double electronP = std::sqrt(std::pow(electronEnergyGeV, 2) - std::pow(electronM, 2));
941 double electronPx = electronDirection.at(0) * electronP;
942 double electronPy = electronDirection.at(1) * electronP;
943 double electronPz = electronDirection.at(2) * electronP;
947 int electronPDG = 11;
950 TLorentzVector electronPosition(vertex.at(0), vertex.at(1), vertex.at(2), neutrinoTime);
951 TLorentzVector electronMomentum(electronPx, electronPy, electronPz, electronEnergyGeV);
956 double ttime = neutrinoTime;
960 int groundLevel = fNumberOfLevels - 1;
961 while (level != groundLevel) {
963 double rl = randFlat.fire();
970 for (
unsigned int iLevel = 0; iLevel <
fBranchingRatios.at(level).size(); ++iLevel) {
976 level =
fDecayTo.at(level).at(decayNum);
980 double gammaEnergyGeV = gammaEnergy / 1000;
983 double gammaPx = gammaDirection.at(0) * gammaEnergyGeV;
984 double gammaPy = gammaDirection.at(1) * gammaEnergyGeV;
985 double gammaPz = gammaDirection.at(2) * gammaEnergyGeV;
990 (-TMath::Log(randFlat.fire()) / (1 / (levelDelay.at(lastLevel)))) + ttime;
999 TLorentzVector gammaPosition(vertex.at(0), vertex.at(1), vertex.at(2), neutrinoTime);
1000 TLorentzVector gammaMomentum(gammaPx, gammaPy, gammaPz, gammaEnergyGeV);
1012 std::cout <<
"(tprob + *iLevel) > 1" << std::endl;
1022 if (noMoreDecay == 1)
break;
1027 std::cout <<
"level != 72" << std::endl;
1028 std::cout <<
"level = " << level << std::endl;
1054 int& highestLevel)
const 1058 std::vector<double> levelCrossSections;
1069 for (
int n = 0;
n <= level; ++
n) {
1073 double p = std::sqrt(pow(w, 2) - pow(511.0, 2));
1075 double f = std::sqrt(3.0634 + (0.6814 / (w - 1)));
1077 sigma += 1.6e-8 * (p * w * f *
fB.at(
n));
1080 levelCrossSections.push_back(sigma);
1083 return levelCrossSections;
void AddTrajectoryPoint(TLorentzVector const &position, TLorentzVector const &momentum)
bool ProcessOneNeutrino(simb::MCTruth &truth, double neutrinoEnergy, double neutrinoTime, CLHEP::HepRandomEngine &engine) const
void SetOrigin(simb::Origin_t origin)
double fNeutrinoTimeBegin
std::vector< double > GetUniformPosition(CLHEP::HepRandomEngine &engine) const
constexpr auto abs(T v)
Returns the absolute value of the argument.
void CreateKinematicsVector(simb::MCTruth &truth, CLHEP::HepRandomEngine &engine) const
void SetNeutrino(int CCNC, int mode, int interactionType, int target, int nucleon, int quark, double w, double x, double y, double qsqr)
charged current quasi-elastic
std::vector< double > GetIsotropicDirection(CLHEP::HepRandomEngine &engine) const
bool fUsePoissonDistribution
bool fMonoenergeticNeutrinos
std::vector< std::vector< double > > fBranchingRatios
double GetNeutrinoTime(CLHEP::HepRandomEngine &engine) const
std::vector< double > CalculateCrossSections(double neutrinoEnergy, int &highestLevel) const
int GetNumberOfNeutrinos(CLHEP::HepRandomEngine &engine) const
NueAr40CCGenerator(fhicl::ParameterSet const ¶meterSet)
T get(std::string const &key) const
std::vector< std::vector< int > > fDecayTo
std::vector< double > fStartEnergyLevels
double GetNeutrinoEnergy(CLHEP::HepRandomEngine &engine) const
void Add(simb::MCParticle const &part)
decltype(auto) get(T &&obj)
ADL-aware version of std::to_string.
std::vector< std::vector< double > > fActiveVolume
std::string fEnergySpectrumFileName
std::map< double, double > fEnergyProbabilityMap
std::vector< simb::MCTruth > Generate(CLHEP::HepRandomEngine &engine)
Event generator information.
second_as<> second
Type of time stored in seconds, in double precision.
Event Generation using GENIE, cosmics or single particles.
cet::coded_exception< error, detail::translate > exception
std::vector< double > fEnergyLevels
void ReadNeutrinoSpectrum()