10 #include "cetlib/search_path.h"
11 #include "cetlib_except/exception.h"
12 #include "fhiclcpp/ParameterSet.h"
15 #include "nusimdata/SimulationBase/MCNeutrino.h"
16 #include "nusimdata/SimulationBase/MCTruth.h"
17 #include "nusimdata/SimulationBase/MCParticle.h"
23 #include "TLorentzVector.h"
25 #include "CLHEP/Random/RandFlat.h"
26 #include "CLHEP/Random/RandPoisson.h"
39 : fNumberOfLevels ( 73 )
40 , fNumberOfStartLevels ( 21 )
41 , fBranchingRatios (fNumberOfLevels )
42 , fDecayTo (fNumberOfLevels )
43 , fMonoenergeticNeutrinos
44 (parameterSet.
get<
bool >(
"MonoenergeticNeutrinos"))
46 (parameterSet.
get< double >(
"NeutrinoEnergy" ))
47 , fEnergySpectrumFileName
48 (parameterSet.
get<
std::string >(
"EnergySpectrumFileName"))
49 , fUsePoissonDistribution
50 (parameterSet.
get<
bool >(
"UsePoissonDistribution"))
52 (parameterSet.
get<
bool >(
"AllowZeroNeutrinos" ))
54 (parameterSet.
get< int >(
"NumberOfNeutrinos" ))
56 (parameterSet.
get< double >(
"NeutrinoTimeBegin" ))
58 (parameterSet.
get< double >(
"NeutrinoTimeEnd" ))
62 (parameterSet.get< std::vector< double > >(
"ActiveVolume0"));
64 (parameterSet.get< std::vector< double > >(
"ActiveVolume1"));
77 std::vector<simb::MCTruth> truths;
80 for(
int i = 0; i < NumberOfNu; ++i) {
83 truth.SetOrigin(simb::kSuperNovaNeutrino);
86 while (!truth.NParticles()) {
90 truths.push_back(truth);
101 (CLHEP::HepRandomEngine& engine)
const
104 CLHEP::RandFlat randFlat(engine);
106 std::vector< double > isotropicDirection;
108 double phi = 2*TMath::Pi()*randFlat.fire();
109 double cosTheta = 2*randFlat.fire() - 1;
110 double theta = TMath::ACos(cosTheta);
113 isotropicDirection.push_back(cos(phi)*sin(theta));
114 isotropicDirection.push_back(sin(phi)*sin(theta));
115 isotropicDirection.push_back(cosTheta);
117 return isotropicDirection;
124 (CLHEP::HepRandomEngine& engine)
const
127 CLHEP::RandFlat randFlat(engine);
129 std::vector< double > position;
131 position.push_back(randFlat.
132 fire(fActiveVolume.at(0).at(0), fActiveVolume.at(1).at(0)));
133 position.push_back(randFlat.
134 fire(fActiveVolume.at(0).at(1), fActiveVolume.at(1).at(1)));
135 position.push_back(randFlat.
136 fire(fActiveVolume.at(0).at(2), fActiveVolume.at(1).at(2)));
145 (CLHEP::HepRandomEngine& engine)
const
148 if (fUsePoissonDistribution)
150 CLHEP::RandPoisson randPoisson(engine);
151 int N = randPoisson.fire(fNumberOfNeutrinos);
152 if(N == 0 && !fAllowZeroNeutrinos) N = 1;
156 return fNumberOfNeutrinos;
163 (CLHEP::HepRandomEngine& engine)
const
166 CLHEP::RandFlat randFlat(engine);
168 return randFlat.fire(fNeutrinoTimeBegin, fNeutrinoTimeEnd);
176 (CLHEP::HepRandomEngine& engine)
const
179 if (fMonoenergeticNeutrinos)
return fNeutrinoEnergy;
181 CLHEP::RandFlat randFlat(engine);
183 double neutrinoEnergy = 0.0;
185 double randomNumber = randFlat.fire();
188 std::pair< double, double > previousPair;
190 for (std::map< double, double >::const_iterator energyProbability =
191 fEnergyProbabilityMap.begin(); energyProbability !=
192 fEnergyProbabilityMap.end(); ++energyProbability)
194 if (randomNumber < energyProbability->
second)
196 if (energyProbability != fEnergyProbabilityMap.begin())
198 neutrinoEnergy = energyProbability->first -
199 (energyProbability->second - randomNumber)*
200 (energyProbability->first - previousPair.first)/
201 (energyProbability->second - previousPair.second);
206 neutrinoEnergy = energyProbability->first;
210 previousPair = *energyProbability;
213 return neutrinoEnergy;
222 cet::search_path searchPath(
"FW_SEARCH_PATH");
223 std::string directoryName =
"SupernovaNeutrinos/" +
226 std::string fullName;
227 searchPath.find_file(directoryName, fullName);
229 if (fullName.empty())
230 throw cet::exception(
"NueAr40CCGenerator")
231 <<
"Cannot find file with neutrino energy spectrum "
234 TFile energySpectrumFile(fullName.c_str(),
"READ");
236 std::string energySpectrumGraphName =
"NueSpectrum";
237 TGraph *energySpectrumGraph =
238 dynamic_cast< TGraph*
>(energySpectrumFile.Get
239 (energySpectrumGraphName.c_str()));
241 double integral = 0.0;
242 int numberOfPoints = energySpectrumGraph->GetN();
243 double *energyValues = energySpectrumGraph->GetX();
244 double *fluxValues = energySpectrumGraph->GetY();
245 for (
int point = 0; point < numberOfPoints; ++point)
246 integral += fluxValues[point];
248 double probability = 0.0;
249 for (
int point = 0; point < numberOfPoints; ++point)
251 probability += fluxValues[point]/integral;
804 double startEnergyLevels[] = { 2.281, 2.752, 2.937,
805 3.143, 3.334, 3.569, 3.652, 3.786, 3.861, 4.067, 4.111, 4.267,
806 4.364, 4.522, 4.655, 4.825, 5.017, 5.080, 5.223, 5.696, 6.006 };
811 double b[] = { 0.9, 1.5, 0.11, 0.06, 0.04, 0.01,
812 0.16, 0.26, 0.01, 0.05, 0.11, 0.29,
813 3.84, 0.31, 0.38, 0.47, 0.36, 0.23,
818 double energyLevels[] = { 7.4724, 6.2270, 5.06347,
819 4.99294, 4.8756, 4.87255, 4.78865, 4.744093, 4.53706,
820 4.47299, 4.41936, 4.39588, 4.3840, 4.3656, 4.28052,
821 4.25362, 4.21307, 4.18003, 4.14901, 4.11084, 4.10446,
822 4.02035, 3.92390, 3.88792, 3.86866, 3.840228, 3.82143,
823 3.79757, 3.76779, 3.73848, 3.663739, 3.62995, 3.59924,
824 3.55697, 3.48621, 3.439144, 3.41434, 3.39363, 3.36803,
825 3.22867, 3.15381, 3.14644, 3.12836, 3.109721, 3.1002,
826 3.02795, 2.98587, 2.9508, 2.87901, 2.80788, 2.7874,
827 2.786644, 2.75672, 2.74691, 2.730372, 2.625990, 2.57593,
828 2.558, 2.54277, 2.419171, 2.397165, 2.290493, 2.289871,
829 2.26040, 2.103668, 2.069809, 2.047354, 1.959068, 1.643639,
830 0.891398, 0.8001427, 0.0298299, 0.0 };
843 CLHEP::HepRandomEngine& engine)
const
846 bool success =
false;
859 double neutrinoEnergy,
double neutrinoTime,
860 CLHEP::HepRandomEngine& engine)
const
863 CLHEP::RandFlat randFlat(engine);
865 int highestLevel = 0;
866 std::vector< double > levelCrossSections =
869 double totalCrossSection = 0;
871 for (std::vector< double >::iterator crossSection =
872 levelCrossSections.begin();
873 crossSection != levelCrossSections.end(); ++crossSection)
874 totalCrossSection += *crossSection;
876 if (totalCrossSection == 0)
879 std::vector< double > startLevelProbabilities;
881 for (std::vector< double >::iterator crossSection =
882 levelCrossSections.begin();
883 crossSection != levelCrossSections.end(); ++crossSection)
884 startLevelProbabilities.push_back((*crossSection)/totalCrossSection);
886 double randomNumber = randFlat.fire();
888 int chosenStartLevel = -1;
890 for (
int level = 0; level < highestLevel; ++level)
892 if (randomNumber < (startLevelProbabilities.at(level) + tprob))
894 chosenStartLevel = level;
897 tprob += startLevelProbabilities.at(level);
905 std::vector< double > levelDelay;
910 int highestHigher = 0;
932 lastLevel = lowestLower;
945 lastLevel = highestHigher;
946 level = highestHigher;
965 int neutrinoTrackID = -1*(truth.NParticles() + 1);
966 std::string primary(
"primary");
969 double neutrinoP = neutrinoEnergy/1000.0;
970 double neutrinoPx = neutrinoDirection.at(0)*neutrinoP;
971 double neutrinoPy = neutrinoDirection.at(1)*neutrinoP;
972 double neutrinoPz = neutrinoDirection.at(2)*neutrinoP;
980 simb::MCParticle neutrino(neutrinoTrackID, nuePDG, primary, -1, -1, 0);
982 TLorentzVector neutrinoPosition(vertex.at(0), vertex.at(1),
983 vertex.at(2), neutrinoTime);
984 TLorentzVector neutrinoMomentum(neutrinoPx, neutrinoPy,
985 neutrinoPz, neutrinoEnergy/1000.0);
986 neutrino.AddTrajectoryPoint(neutrinoPosition, neutrinoMomentum);
997 double electronEnergy = neutrinoEnergy -
999 double electronEnergyGeV = electronEnergy/1000.0;
1001 double electronM = 0.000511;
1002 double electronP = std::sqrt(std::pow(electronEnergyGeV,2)
1003 - std::pow(electronM,2));
1007 double electronPx = electronDirection.at(0)*electronP;
1008 double electronPy = electronDirection.at(1)*electronP;
1009 double electronPz = electronDirection.at(2)*electronP;
1012 int trackID = -1*(truth.NParticles() + 1);
1013 int electronPDG = 11;
1014 simb::MCParticle electron(trackID, electronPDG, primary);
1016 TLorentzVector electronPosition(vertex.at(0), vertex.at(1),
1017 vertex.at(2), neutrinoTime);
1018 TLorentzVector electronMomentum(electronPx, electronPy,
1019 electronPz, electronEnergyGeV);
1020 electron.AddTrajectoryPoint(electronPosition, electronMomentum);
1022 truth.Add(electron);
1024 double ttime = neutrinoTime;
1025 int noMoreDecay = 0;
1028 int groundLevel = fNumberOfLevels - 1;
1029 while (level != groundLevel)
1032 double rl = randFlat.fire();
1039 for (
unsigned int iLevel = 0;
1048 level =
fDecayTo.at(level).at(decayNum);
1053 double gammaEnergyGeV = gammaEnergy/1000;
1056 double gammaPx = gammaDirection.at(0)*gammaEnergyGeV;
1057 double gammaPy = gammaDirection.at(1)*gammaEnergyGeV;
1058 double gammaPz = gammaDirection.at(2)*gammaEnergyGeV;
1062 double gammaTime = (-TMath::Log(randFlat.fire())/
1063 (1/(levelDelay.at(lastLevel)))) + ttime;
1068 trackID = -1*(truth.NParticles() + 1);
1070 simb::MCParticle gamma(trackID, gammaPDG, primary);
1072 TLorentzVector gammaPosition(vertex.at(0), vertex.at(1),
1073 vertex.at(2), neutrinoTime);
1074 TLorentzVector gammaMomentum(gammaPx, gammaPy,
1075 gammaPz, gammaEnergyGeV);
1076 gamma.AddTrajectoryPoint(gammaPosition, gammaMomentum);
1088 std::cout <<
"(tprob + *iLevel) > 1" << std::endl;
1098 if (noMoreDecay == 1)
break;
1104 std::cout <<
"level != 72" << std::endl;
1105 std::cout <<
"level = " << level << std::endl;
1131 (
double neutrinoEnergy,
int& highestLevel)
const
1135 std::vector< double > levelCrossSections;
1139 for (
int level = 0; level < fNumberOfStartLevels; ++level)
1142 double w = (neutrinoEnergy - (fStartEnergyLevels.at(level) + 1.5))*1000;
1145 if (neutrinoEnergy > (fStartEnergyLevels.at(level) + 1.5) && w >= 511.)
1148 for (
int n = 0;
n <= level; ++
n)
1151 w = (neutrinoEnergy - (fStartEnergyLevels.at(
n) + 1.5))*1000;
1153 double p = std::sqrt(pow(w, 2) - pow(511.0, 2));
1155 double f = std::sqrt(3.0634 + (0.6814/(w - 1)));
1157 sigma += 1.6e-8*(p*w*f*fB.at(
n));
1160 levelCrossSections.push_back(sigma);
1163 return levelCrossSections;
std::vector< double > fStartEnergyLevels
double std(const std::vector< short > &wf, const double ped_mean, size_t start, size_t nsample)
bool ProcessOneNeutrino(simb::MCTruth &truth, double neutrinoEnergy, double neutrinoTime, CLHEP::HepRandomEngine &engine) const
std::vector< double > GetUniformPosition(CLHEP::HepRandomEngine &engine) const
std::vector< double > fEnergyLevels
void CreateKinematicsVector(simb::MCTruth &truth, CLHEP::HepRandomEngine &engine) const
std::vector< std::vector< double > > fBranchingRatios
std::vector< double > GetIsotropicDirection(CLHEP::HepRandomEngine &engine) const
Charged-current interactions.
bool fMonoenergeticNeutrinos
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)
std::map< double, double > fEnergyProbabilityMap
double GetNeutrinoEnergy(CLHEP::HepRandomEngine &engine) const
std::string fEnergySpectrumFileName
process_name largeant stream1 can override from command line with o or output physics producers generator N
std::vector< simb::MCTruth > Generate(CLHEP::HepRandomEngine &engine)
charged current quasi-elastic
std::vector< std::vector< double > > fActiveVolume
std::vector< std::vector< int > > fDecayTo
BEGIN_PROLOG could also be cout
void ReadNeutrinoSpectrum()