From e2b3b706db139a5752377af83a9120c74b009d4e Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Wed, 15 Apr 2026 07:49:38 -0500 Subject: [PATCH 01/14] First version of Dark Photon MeVPrtl implementation --- .../MeVPrtl/Tools/BNBKaonGenDK2NU_tool.cc | 1257 +++++++++++++++++ .../MeVPrtl/Tools/BNBPi0Gen_tool.cc | 332 +++++ .../MeVPrtl/Tools/Constants.cpp | 6 +- .../EventGenerator/MeVPrtl/Tools/Constants.h | 1 + .../MeVPrtl/Tools/DP/CMakeLists.txt | 108 ++ .../MeVPrtl/Tools/DP/DPDecay_tool.cc | 306 ++++ .../MeVPrtl/Tools/DP/Meson2DP_tool.cc | 204 +++ .../MeVPrtl/Tools/DP/old/CMakeLists.txt | 107 ++ .../MeVPrtl/Tools/DP/old/DPMakeDecay_tool.cc | 239 ++++ .../MeVPrtl/Tools/DP/old/Eta2DPFlux_tool.cc | 231 +++ .../Tools/DP/old/PiZero2DPFlux_tool.cc | 275 ++++ .../MeVPrtl/Tools/TxtFileGenNM_tool.cc | 360 +++++ .../MeVPrtl/config/DP/CMakeLists.txt | 1 + .../EventGenerator/MeVPrtl/config/DP/dp.fcl | 88 ++ .../MeVPrtl/config/DP/run_dp.fcl | 46 + .../MeVPrtl/config/bnb_dp_common.fcl | 62 + .../MeVPrtl/config/bnb_dp_sbnd.fcl | 58 + 17 files changed, 3680 insertions(+), 1 deletion(-) create mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/BNBKaonGenDK2NU_tool.cc create mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/BNBPi0Gen_tool.cc create mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/CMakeLists.txt create mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/DPDecay_tool.cc create mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc create mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/old/CMakeLists.txt create mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/old/DPMakeDecay_tool.cc create mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/old/Eta2DPFlux_tool.cc create mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/old/PiZero2DPFlux_tool.cc create mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/TxtFileGenNM_tool.cc create mode 100644 sbncode/EventGenerator/MeVPrtl/config/DP/CMakeLists.txt create mode 100644 sbncode/EventGenerator/MeVPrtl/config/DP/dp.fcl create mode 100644 sbncode/EventGenerator/MeVPrtl/config/DP/run_dp.fcl create mode 100644 sbncode/EventGenerator/MeVPrtl/config/bnb_dp_common.fcl create mode 100644 sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/BNBKaonGenDK2NU_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/BNBKaonGenDK2NU_tool.cc new file mode 100644 index 000000000..25b1dbed4 --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/Tools/BNBKaonGenDK2NU_tool.cc @@ -0,0 +1,1257 @@ +// /** +// * +// */ + +// // Framework Includes +// #include "art/Framework/Core/EDProducer.h" +// #include "art/Framework/Principal/Event.h" +// #include "art/Framework/Principal/Handle.h" +// #include "art/Framework/Services/Registry/ServiceHandle.h" +// #include "art/Persistency/Common/PtrMaker.h" +// #include "art/Utilities/ToolMacros.h" +// #include "cetlib/cpu_timer.h" +// #include "fhiclcpp/ParameterSet.h" +// #include "messagefacility/MessageLogger/MessageLogger.h" +// #include "CLHEP/Random/RandFlat.h" +// #include "ifdh_art/IFDHService/IFDH_service.h" + +// #include "nusimdata/SimulationBase/MCFlux.h" + +// // local includes +// #include "IMesonGen.h" +// #include "boone.h" +// #include "PDGCodes.h" + +// // LArSoft includes +// #include "dk2nu/tree/dk2nu.h" +// #include "dk2nu/tree/dkmeta.h" +// #include "dk2nu/tree/NuChoice.h" + +// // ROOT +// #include "TVector3.h" +// #include "TTree.h" +// #include "TFile.h" +// #include "TTreeReader.h" +// #include "TTreeReaderValue.h" + +// // std includes +// #include +// #include +// #include + +// //------------------------------------------------------------------------------------------------------------------------------------------ +// // implementation follows + +// namespace evgen { +// namespace ldm { +// /** +// * @brief BNBKaonGen class definiton +// */ +// class BNBKaonGen : public IMesonGen +// { +// public: +// /** +// * @brief Constructor +// */ +// BNBKaonGen(fhicl::ParameterSet const &pset); + +// /** +// * @brief Destructor +// */ +// ~BNBKaonGen(); + +// double GetPOT() override; +// simb::MCFlux GetNext() override; + +// void configure(const fhicl::ParameterSet&) override; + +// const bsim::Dk2Nu *GetNextEntry(); +// const bsim::BooNe *GetNextEntry(); +// std::vector LoadFluxFiles(); +// simb::MCFlux MakeMCFlux(const bsim::Dk2Nu &dk2nu); +// simb::MCFlux MakeMCFlux(const bsim::BooNe &boone); +// double LoadPOT(); + +// // no weights +// double MaxWeight() override { return -1.; } + +// private: +// // config +// std::string fSearchPath; +// std::vector fSearchPatterns; +// unsigned long fMaxFluxFileMB; +// std::string fFluxCopyMethod; +// bool fRandomizeFiles; +// bool fVerbose; + +// std::string fTreeName; +// std::string fMetaTreeName; + +// // info for tracking files +// unsigned fFileIndex; +// bool fNewFile; +// std::vector fFluxFiles; + +// // info for tracking entry in file +// unsigned fEntry; +// unsigned fEntryStart; + +// // ROOT Holders +// TTree *fFluxTree; +// TFile *fFluxFile; +// bsim::Dk2Nu *fDk2Nu; +// bsim::BooNe *fBooNe; + +// // count POT +// double fAccumulatedPOT; +// double fThisFilePOT; + +// }; + +// BNBKaonGen::BNBKaonGen(fhicl::ParameterSet const &pset): +// IMeVPrtlStage("BNBKaonGen") +// { +// configure(pset); + +// // copy the flux files locally +// fFluxFiles = LoadFluxFiles(); + +// // setup indices +// fFileIndex = 0; +// fEntry = 0; +// fEntryStart = 0; +// fNewFile = true; +// fFluxTree = NULL; +// fFluxFile = NULL; +// fDk2Nu = new bsim::Dk2Nu; +// fBooNe = new bsim::BooNe; + +// fAccumulatedPOT = 0.; +// fThisFilePOT = 0.; + +// } + +// //------------------------------------------------------------------------------------------------------------------------------------------ + +// BNBKaonGen::~BNBKaonGen() +// { + +// if (fDk2Nu) delete fDk2Nu; +// if (fBooNe) delete fBooNe; +// } + +// //------------------------------------------------------------------------------------------------------------------------------------------ +// void BNBKaonGen::configure(fhicl::ParameterSet const &pset) +// { +// fSearchPath = pset.get("SearchPath"); +// fSearchPatterns = pset.get>("FluxFiles"); +// fMaxFluxFileMB = pset.get("MaxFluxFileMB", 2 * 1024); +// fFluxCopyMethod = pset.get("FluxCopyMethod", "IFDH"); +// fTreeName = pset.get("TreeName"); +// fMetaTreeName = pset.get("MetaTreeName"); +// fRandomizeFiles = pset.get("RandomizeFiles"); +// fVerbose = pset.get("Verbose", true); +// fFluxMode = pset.get("FluxMode", "G4BNB"); +// if (fFluxMode != "BooNE" && fFluxMode != "Dk2Nu") { +// throw cet::exception("BNBKaonGen") +// << "Invalid FluxMode = " << fFluxMode +// << " (allowed: BooNE, Dk2Nu)"; +// } + + +// if(fVerbose){ +// std::cout << "Searching for flux files at path: " << fSearchPath << std::endl; +// std::cout << "With patterns:\n"; +// for (const std::string &s: fSearchPatterns) std::cout << s << std::endl; +// std::cout << "With copy method: " << fFluxCopyMethod << std::endl; +// } + +// } + +// std::vector BNBKaonGen::LoadFluxFiles() { +// art::ServiceHandle ifdhp; + +// std::vector> allFiles; + +// // find the flux files +// for (unsigned i = 0; i < fSearchPatterns.size(); i++) { +// std::vector> thisList = ifdhp->findMatchingFiles(fSearchPath, fSearchPatterns[i]); +// std::copy (thisList.begin(), thisList.end(), std::back_inserter(allFiles)); +// } + +// // first randomize the flux files +// std::vector order(allFiles.size(), 0); +// if (fRandomizeFiles) { +// std::vector rand(allFiles.size(), 0.); +// CLHEP::RandFlat::shootArray(fEngine, rand.size(), &rand[0]); +// TMath::Sort(allFiles.size(), &rand[0], &order[0], false); +// } +// else { +// for (unsigned i = 0; i < order.size(); i++) { +// order[i] = i; +// } +// } + +// // If we are directly accessing the files, no need to copy +// if (fFluxCopyMethod == "DIRECT") { +// if(fVerbose) std::cout << "DIRECTLY ACCESSING FLUX FILES.\n"; +// std::vector files(allFiles.size()); +// for (unsigned i = 0; i < order.size(); i++) { +// files[i] = allFiles[order[i]].first; +// } +// return files; +// } + +// // copy over up to the provided limit +// std::vector> selected; +// unsigned long totalBytes = 0; +// unsigned ind = 0; +// while (totalBytes < (fMaxFluxFileMB * 1024 * 1024) && ind < allFiles.size()) { +// selected.push_back(allFiles[order[ind]]); +// totalBytes += allFiles[order[ind]].second; +// ind ++; +// } + +// // copy the files locally +// std::vector> localFiles = ifdhp->fetchSharedFiles(selected, fFluxCopyMethod); + +// std::vector files(localFiles.size()); +// for (unsigned i = 0; i < localFiles.size(); i++) { +// files[i] = localFiles[i].first; +// } + +// return files; +// } + +// double BNBKaonGen::LoadPOT() { +// TTreeReader metaReader(fMetaTreeName.c_str(), fFluxFile); +// TTreeReaderValue pot(metaReader, "pots"); + +// double total_pot = 0.; + +// while (metaReader.Next()) { +// total_pot += *pot; +// } + +// return total_pot; +// } + + +// double BNBKaonGen::GetPOT() { +// double ret = fAccumulatedPOT; +// fAccumulatedPOT = 0.; +// return ret; +// } + +// const bsim::BooNe *BNBKaonGen::GetNextEntry() { +// // new file -- set the start entry +// if (fNewFile) { +// // wrap file index around +// if (fFileIndex >= fFluxFiles.size()) { +// fFileIndex = 0; +// } +// // if (fFileIndex >= fFluxFiles.size()) { +// // throw cet::exception("FluxReader Out of Files", +// // "At file index (" + std::to_string(fFileIndex) + ") of available files (" + std::to_string(fFluxFiles.size()) + ")."); +// // } + +// if(fVerbose) std::cout << "New file: " << fFluxFiles[fFileIndex] << " at index: " << fFileIndex << " of: " << fFluxFiles.size() << std::endl; +// if (fFluxFile) delete fFluxFile; +// fFluxFile = new TFile(fFluxFiles[fFileIndex].c_str()); +// fFluxTree = (TTree*)fFluxFile->Get(fTreeName.c_str()); +// // fFluxTree->SetBranchAddress("dk2nu",&fDk2Nu); +// fBooNe = new bsim::BooNe(fFluxFiles[fFileIndex].c_str()); + +// // Start at a random index in this file +// fEntryStart = CLHEP::RandFlat::shootInt(fEngine, fFluxTree->GetEntries()-1); +// fEntry = fEntryStart; + +// // load the POT in this file +// // fThisFilePOT = LoadPOT(); +// fNewFile = false; +// } +// else { +// fEntry = (fEntry + 1) % fFluxTree->GetEntries(); +// // if this is the last entry, get ready for the next file +// if ((fEntry + 1) % fFluxTree->GetEntries() == fEntryStart) { +// fFileIndex ++; +// fNewFile = true; +// } +// } + +// // count the POT +// fBooNe->myNtuple.run = fEntry; +// fBooNe->myNtuple.eventn = fFileIndex; + +// fAccumulatedPOT += fBooNe->GetPOT(); + +// fFluxTree->GetEntry(fEntry); +// fBooNe->GetEntry(fEntry); +// return fBooNe; +// } + +// const bsim::Dk2Nu *BNBKaonGen::GetNextEntry() { +// // new file -- set the start entry +// if (fNewFile) { +// // wrap file index around +// if (fFileIndex >= fFluxFiles.size()) { +// fFileIndex = 0; +// } +// // if (fFileIndex >= fFluxFiles.size()) { +// // throw cet::exception("FluxReader Out of Files", +// // "At file index (" + std::to_string(fFileIndex) + ") of available files (" + std::to_string(fFluxFiles.size()) + ")."); +// // } + +// std::cout << "New file: " << fFluxFiles[fFileIndex] << " at index: " << fFileIndex << " of: " << fFluxFiles.size() << std::endl; +// if (fFluxFile) delete fFluxFile; +// fFluxFile = new TFile(fFluxFiles[fFileIndex].c_str()); +// fFluxTree = (TTree*)fFluxFile->Get(fTreeName.c_str()); +// fFluxTree->SetBranchAddress("dk2nu",&fDk2Nu); + +// // Start at a random index in this file +// fEntryStart = CLHEP::RandFlat::shootInt(fEngine, fFluxTree->GetEntries()-1); +// fEntry = fEntryStart; + +// // load the POT in this file +// fThisFilePOT = LoadPOT(); +// fNewFile = false; +// } +// else { +// fEntry = (fEntry + 1) % fFluxTree->GetEntries(); +// // if this is the last entry, get ready for the next file +// if ((fEntry + 1) % fFluxTree->GetEntries() == fEntryStart) { +// fFileIndex ++; +// fNewFile = true; +// } +// } + +// // count the POT +// fAccumulatedPOT += fThisFilePOT / fFluxTree->GetEntries(); + +// fFluxTree->GetEntry(fEntry); +// return fDk2Nu; +// } + +// simb::MCFlux BNBKaonGen::GetNext() { +// if (fFluxMode == "G4BNB") { +// mf::LogWarning("BNBKaonGen") << "BNBKaonGen is set to G4BNB mode, but this tool only supports BooNE mode. Switching to BooNE mode."; +// const bsim::Dk2Nu *flux = GetNextEntry(); +// } +// else{ +// const bsim::BooNe *flux = GetNextEntry(); +// } +// return MakeMCFlux(*flux); +// } + +// simb::MCFlux BNBKaonGen::MakeMCFlux(const bsim::BooNe &boone) { + +// simb::MCFlux flux; +// auto fBooneNtp=boone.myNtuple; + +// if ( fBooneNtp.ntp == 1 ) { +// flux.fntype = 12; //nue +// } +// else if ( fBooneNtp.ntp == 2 ) { +// flux.fntype = -12; //nuebar +// } +// else if ( fBooneNtp.ntp == 3 ) { +// flux.fntype = 14; //numu +// } +// else if ( fBooneNtp.ntp == 4 ) { +// flux.fntype = -14; //numubar +// } +// else{ +// mf::LogWarning("BooNEInterface") << "Neutrino type not recognized! ntp = " << fBooneNtp.ntp +// << std::endl; +// } + +// flux.fFluxType = simb::kDk2Nu; +// flux.fnimpwt = fBooneNtp.beamwgt; +// flux.fvx = fBooneNtp.ini_pos[0][0]; //0 +// flux.fvy = fBooneNtp.ini_pos[0][1]; //0 +// flux.fvz = fBooneNtp.ini_pos[0][2]; //0 +// flux.fpdpx = fBooneNtp.fin_mom[1][0]; //1 final +// flux.fpdpy = fBooneNtp.fin_mom[1][1]; //1 final +// flux.fpdpz = fBooneNtp.fin_mom[1][2]; //1 final +// flux.fpppz = fBooneNtp.ini_mom[1][2]; //1 init + +// // Momentum projected in dx/dz or dy/dz +// flux.fpppz = fBooneNtp.ini_mom[1][2]; //1 init +// double pppx = fBooneNtp.ini_mom[1][0]; //1 init +// double pppy = fBooneNtp.ini_mom[1][1]; //1 init +// double apppz = flux.fpppz; +// if (TMath::Abs(flux.fpppz) < 1.0e-30) apppz = 1.0e-30; +// flux.fppdxdz = pppx / apppz; +// flux.fppdydz = pppy / apppz; + +// flux.fppmedium = 0.; +// flux.fppenergy = fBooneNtp.ini_eng[1]; + +// int npart = fBooneNtp.npart; +// int ptype_input = fBooneNtp.id[1]; +// int tptype_input = fBooneNtp.id[npart-2]; + +// if (ptype_input != 0) ptype_input = evgen::GeantToPdg(ptype_input); +// if (tptype_input != 0) tptype_input= evgen::GeantToPdg(tptype_input); + +// flux.fptype = ptype_input; +// flux.ftptype = tptype_input; + +// ///// +// // Now need to calculate ndecay +// ///// + +// double Nenergy = fBooneNtp.ini_eng[0]; +// double Ndxdz = fBooneNtp.ini_mom[0][0] / fBooneNtp.ini_mom[0][2]; +// double Ndydz = fBooneNtp.ini_mom[0][1] / fBooneNtp.ini_mom[0][2]; + +// double ppenergy = fBooneNtp.ini_eng[1]; +// double pdPx = fBooneNtp.fin_mom[1][0]; +// double pdPy = fBooneNtp.fin_mom[1][1]; +// double pdPz = fBooneNtp.fin_mom[1][2]; + +// double ppdxdz = fBooneNtp.ini_mom[1][0] / fBooneNtp.ini_mom[1][2]; +// double ppdydz = fBooneNtp.ini_mom[1][1] / fBooneNtp.ini_mom[1][2]; +// double pppz = fBooneNtp.ini_mom[1][2]; + +// // Get the neutrino energy in the parent decay cm +// double parent_mass = std::sqrt(ppenergy * ppenergy - +// pppz * pppz * (ppdxdz * ppdxdz + +// ppdydz * ppdydz + +// 1.)); + +// double parent_energy = std::sqrt(pdPx * pdPx + +// pdPy * pdPy + +// pdPz * pdPz + +// parent_mass * parent_mass); + +// double gamma = parent_energy / parent_mass; +// double beta[3]; +// beta[0] = pdPx / parent_energy; +// beta[1] = pdPy / parent_energy; +// beta[2] = pdPz / parent_energy; + +// double partial = fBooneNtp.ini_mom[0][2] * gamma * +// (beta[0] * Ndxdz + +// beta[1] * Ndydz + +// beta[2]); + +// double Necm = gamma * Nenergy - partial; + +// if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 1) flux.fndecay = 1; +// else if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 2) flux.fndecay = 2; +// else if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 3) flux.fndecay = 3; +// else if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 4) flux.fndecay = 4; +// else if (fBooneNtp.id[1] == 11 && fBooneNtp.ntp == 3) { +// //check if it is a two or three body decay +// if (fabs((parent_mass*parent_mass-0.105658389*0.105658389)/(2.*parent_mass)-Necm)/Necm <= 0.001) +// //two body decay (numu + mu+) +// flux.fndecay = 5; +// else { +// //three body decay (numu + pi0 + mu+) +// flux.fndecay = 7; +// } +// } +// else if (fBooneNtp.id[1] == 11 && fBooneNtp.ntp == 1) flux.fndecay = 6; +// else if (fBooneNtp.id[1] == 12 && fBooneNtp.ntp == 4) { +// if (fabs((parent_mass*parent_mass-0.105658389*0.105658389)/(2.*parent_mass)-Necm)/Necm <= 0.001) { +// //two body decay (numu + mu+) +// flux.fndecay = 8; +// } +// else { +// //three body decay (numu + pi0 + mu+) +// flux.fndecay = 10; +// } +// } +// else if (fBooneNtp.id[1] == 12 && fBooneNtp.ntp == 2) flux.fndecay = 9; +// else if (fBooneNtp.id[1] == 5 ) flux.fndecay = 11; +// else if (fBooneNtp.id[1] == 6 ) flux.fndecay = 12; +// else if (fBooneNtp.id[1] == 8 ) flux.fndecay = 13; +// else if (fBooneNtp.id[1] == 9 ) flux.fndecay = 14; + +// ///// +// // End calculation of ndecay +// ///// +// double mupare; +// double muparpx; +// double muparpy; +// double muparpz; + +// if ( fBooneNtp.id[1] == 5 || fBooneNtp.id[1] == 6) { +// mupare = fBooneNtp.ini_eng[2]; +// muparpx = fBooneNtp.fin_mom[2][0]; +// muparpy = fBooneNtp.fin_mom[2][1]; +// muparpz = fBooneNtp.fin_mom[2][2]; +// } else { +// mupare = -9999.; +// muparpx = -9999.; +// muparpy = -9999.; +// muparpz = -9999.; +// } + +// flux.fmuparpx = muparpx; +// flux.fmuparpy = muparpy; +// flux.fmuparpz = muparpz; +// flux.fmupare = mupare; + +// flux.fnecm = Necm; + +// flux.fppvx = fBooneNtp.ini_pos[1][0]; +// flux.fppvy = fBooneNtp.ini_pos[1][1]; +// flux.fppvz = fBooneNtp.ini_pos[1][2]; + +// flux.ftvx = fBooneNtp.ini_pos[npart-2][0]; +// flux.ftvy = fBooneNtp.ini_pos[npart-2][1]; +// flux.ftvz = fBooneNtp.ini_pos[npart-2][2]; +// flux.ftpx = fBooneNtp.ini_mom[npart-2][0]; +// flux.ftpy = fBooneNtp.ini_mom[npart-2][1]; +// flux.ftpz = fBooneNtp.ini_mom[npart-2][2]; +// // flux.ftgen = dk2nu.tgtexit.tgen; + +// flux.frun = fBooneNtp.run; +// flux.fevtno = fBooneNtp.eventn; +// flux.ftgptype = evgen::GeantToPdg(fBooneNtp.id[npart-2]); + +// // flux.fnenergyn = flux.fnenergyf = enu; +// // flux.fnwtnear = flux.fnwtfar = wgt; +// // ignore variables dealing with the neutrino +// flux.fnenergyn = -1; +// flux.fnwtnear = flux.fnwtfar = -1; +// flux.fdk2gen = -1; + +// // // placeholder for time +// flux.fxpoint = fBooneNtp.ini_t[0]; + +// return flux; +// } + +// simb::MCFlux BNBKaonGen::MakeMCFlux(const bsim::Dk2Nu &dk2nu) { +// simb::MCFlux flux; + +// flux.fFluxType = simb::kDk2Nu; +// flux.fntype = dk2nu.decay.ntype; +// flux.fnimpwt = dk2nu.decay.nimpwt; +// flux.fvx = dk2nu.decay.vx; +// flux.fvy = dk2nu.decay.vy; +// flux.fvz = dk2nu.decay.vz; +// flux.fpdpx = dk2nu.decay.pdpx; +// flux.fpdpy = dk2nu.decay.pdpy; +// flux.fpdpz = dk2nu.decay.pdpz; +// flux.fppdxdz = dk2nu.decay.ppdxdz; +// flux.fppdydz = dk2nu.decay.ppdydz; +// flux.fpppz = dk2nu.decay.pppz; +// flux.fppenergy = dk2nu.decay.ppenergy; +// flux.fppmedium = dk2nu.decay.ppmedium; +// flux.fptype = dk2nu.decay.ptype; +// flux.fndecay = dk2nu.decay.ndecay; +// flux.fmuparpx = dk2nu.decay.muparpx; +// flux.fmuparpy = dk2nu.decay.muparpy; +// flux.fmuparpz = dk2nu.decay.muparpz; +// flux.fmupare = dk2nu.decay.mupare; +// flux.fnecm = dk2nu.decay.necm; + +// flux.fppvx = dk2nu.ppvx; +// flux.fppvy = dk2nu.ppvy; +// flux.fppvz = dk2nu.ppvz; + +// flux.ftvx = dk2nu.tgtexit.tvx; +// flux.ftvy = dk2nu.tgtexit.tvy; +// flux.ftvz = dk2nu.tgtexit.tvz; +// flux.ftpx = dk2nu.tgtexit.tpx; +// flux.ftpy = dk2nu.tgtexit.tpy; +// flux.ftpz = dk2nu.tgtexit.tpz; +// flux.ftptype = dk2nu.tgtexit.tptype; +// flux.ftgen = dk2nu.tgtexit.tgen; + +// flux.frun = dk2nu.job; +// flux.fevtno = dk2nu.potnum; +// flux.ftgptype = dk2nu.ancestor[1].pdg; + +// // flux.fnenergyn = flux.fnenergyf = enu; +// // flux.fnwtnear = flux.fnwtfar = wgt; +// // ignore variables dealing with the neutrino +// flux.fnenergyn = -1; +// flux.fnwtnear = flux.fnwtfar = -1; +// flux.fdk2gen = -1; + +// // placeholder for time +// flux.fxpoint = dk2nu.ancestor.back().startt; + +// return flux; +// } + + +// DEFINE_ART_CLASS_TOOL(BNBKaonGen) + +// } // namespace ldm +// } // namespace evgen + + +/** + * + */ + +// Framework Includes +#include "art/Framework/Core/EDProducer.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art/Persistency/Common/PtrMaker.h" +#include "art/Utilities/ToolMacros.h" +#include "cetlib/cpu_timer.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "CLHEP/Random/RandFlat.h" +#include "ifdh_art/IFDHService/IFDH_service.h" + +#include "nusimdata/SimulationBase/MCFlux.h" + +// local includes +#include "IMesonGen.h" +#include "boone.h" +#include "PDGCodes.h" + +// LArSoft includes +#include "dk2nu/tree/dk2nu.h" +#include "dk2nu/tree/dkmeta.h" +#include "dk2nu/tree/NuChoice.h" + +// ROOT +#include "TVector3.h" +#include "TTree.h" +#include "TFile.h" +#include "TTreeReader.h" +#include "TTreeReaderValue.h" + +// std includes +#include +#include +#include + +//------------------------------------------------------------------------------------------------------------------------------------------ +// implementation follows + +namespace evgen { +namespace ldm { + +/** + * @brief BNBKaonGenDK2NU class definition + */ +class BNBKaonGenDK2NU : public IMesonGen +{ +public: + BNBKaonGenDK2NU(fhicl::ParameterSet const &pset); + ~BNBKaonGenDK2NU(); + + double GetPOT() override; + simb::MCFlux GetNext() override; + + void configure(const fhicl::ParameterSet&) override; + + // Unified interface + void GetNextEntry(); + simb::MCFlux BuildMCFlux(); + + std::vector LoadFluxFiles(); + simb::MCFlux MakeMCFlux(const bsim::Dk2Nu &dk2nu); + simb::MCFlux MakeMCFlux(const bsim::BooNe &boone); + double LoadPOT(); + + // no weights + double MaxWeight() override { return -1.; } + +private: + // ------------------------ + // Configuration parameters + // ------------------------ + std::string fSearchPath; + std::vector fSearchPatterns; + unsigned long fMaxFluxFileMB; + std::string fFluxCopyMethod; + bool fRandomizeFiles; + bool fVerbose; + + std::string fTreeName; + std::string fMetaTreeName; + std::string fFluxMode; // BooNE or Dk2Nu + + // ------------------------ + // File tracking + // ------------------------ + unsigned fFileIndex; + bool fNewFile; + std::vector fFluxFiles; + + // ------------------------ + // Entry tracking + // ------------------------ + unsigned fEntry; + unsigned fEntryStart; + + // ------------------------ + // ROOT holders + // ------------------------ + TTree *fFluxTree; + TFile *fFluxFile; + bsim::Dk2Nu *fDk2Nu; + bsim::BooNe *fBooNe; + + bool fBranchesInitialized = false; + + // ------------------------ + // POT accounting + // ------------------------ + double fAccumulatedPOT; + double fThisFilePOT; + + // Internal helpers + void InitBranches(); +}; + +// ============================================================================ +// Constructor +// ============================================================================ + +BNBKaonGenDK2NU::BNBKaonGenDK2NU(fhicl::ParameterSet const &pset): + IMeVPrtlStage("BNBKaonGenDK2NU") +{ + configure(pset); + + // Copy the flux files locally + fFluxFiles = LoadFluxFiles(); + + // Initialize indices + fFileIndex = 0; + fEntry = 0; + fEntryStart = 0; + fNewFile = true; + fFluxTree = nullptr; + fFluxFile = nullptr; + + // Allocate buffers + fDk2Nu = new bsim::Dk2Nu; + fBooNe = new bsim::BooNe; + + fAccumulatedPOT = 0.; + fThisFilePOT = 0.; +} + +// ============================================================================ +// Destructor +// ============================================================================ + +BNBKaonGenDK2NU::~BNBKaonGenDK2NU() +{ + if (fDk2Nu) delete fDk2Nu; + if (fBooNe) delete fBooNe; +} + +// ============================================================================ +// Configure +// ============================================================================ + +void BNBKaonGenDK2NU::configure(fhicl::ParameterSet const &pset) +{ + fSearchPath = pset.get("SearchPath"); + fSearchPatterns = pset.get>("FluxFiles"); + fMaxFluxFileMB = pset.get("MaxFluxFileMB", 2 * 1024); + fFluxCopyMethod = pset.get("FluxCopyMethod", "IFDH"); + fTreeName = pset.get("TreeName"); + fMetaTreeName = pset.get("MetaTreeName"); + fRandomizeFiles = pset.get("RandomizeFiles"); + fVerbose = pset.get("Verbose", true); + + // Read flux mode from FHiCL + fFluxMode = pset.get("FluxMode", "BooNE"); + + // Normalize user input + if (fFluxMode == "boone") fFluxMode = "BooNE"; + else if (fFluxMode == "dk2nu") fFluxMode = "Dk2Nu"; + + // Validate mode + if (fFluxMode != "BooNE" && fFluxMode != "Dk2Nu") { + throw cet::exception("BNBKaonGenDK2NU") + << "Invalid FluxMode = " << fFluxMode + << " (allowed values: BooNE, Dk2Nu)"; + } + + // Log confirmation + mf::LogInfo("BNBKaonGenDK2NU") + << "============================================\n" + << " BNBKaonGenDK2NU running in FluxMode = " << fFluxMode << "\n" + << "============================================"; + + if (fVerbose) { + std::cout << "Searching for flux files at path: " << fSearchPath << std::endl; + std::cout << "With patterns:\n"; + for (const std::string &s: fSearchPatterns) std::cout << s << std::endl; + std::cout << "With copy method: " << fFluxCopyMethod << std::endl; + } +} + +// ============================================================================ +// Initialize ROOT branches depending on FluxMode +// ============================================================================ + +void BNBKaonGenDK2NU::InitBranches() +{ + if (fBranchesInitialized) return; + + if (!fFluxTree) { + throw cet::exception("BNBKaonGenDK2NU") << "Flux tree is not initialized"; + } + + if (fFluxMode == "Dk2Nu") { + // Bind dk2nu branch only in Dk2Nu mode + fFluxTree->SetBranchAddress("dk2nu", &fDk2Nu); + mf::LogInfo("BNBKaonGenDK2NU") << "Initialized dk2nu branch"; + } + else { + // BooNE reader manages its own file access + mf::LogInfo("BNBKaonGenDK2NU") << "Using BooNE reader (no ROOT branch binding)"; + } + + fBranchesInitialized = true; +} + +// ============================================================================ +// Load flux files +// ============================================================================ + +std::vector BNBKaonGenDK2NU::LoadFluxFiles() +{ + art::ServiceHandle ifdhp; + + std::vector> allFiles; + + // Find all matching flux files + for (unsigned i = 0; i < fSearchPatterns.size(); i++) { + auto thisList = ifdhp->findMatchingFiles(fSearchPath, fSearchPatterns[i]); + std::copy(thisList.begin(), thisList.end(), std::back_inserter(allFiles)); + } + + // Randomize file order if requested + std::vector order(allFiles.size(), 0); + if (fRandomizeFiles) { + std::vector rand(allFiles.size(), 0.); + CLHEP::RandFlat::shootArray(fEngine, rand.size(), &rand[0]); + TMath::Sort(allFiles.size(), &rand[0], &order[0], false); + } + else { + for (unsigned i = 0; i < order.size(); i++) { + order[i] = i; + } + } + + // Direct access mode + if (fFluxCopyMethod == "DIRECT") { + if (fVerbose) std::cout << "DIRECTLY ACCESSING FLUX FILES.\n"; + std::vector files(allFiles.size()); + for (unsigned i = 0; i < order.size(); i++) { + files[i] = allFiles[order[i]].first; + } + return files; + } + + // Copy files up to size limit + std::vector> selected; + unsigned long totalBytes = 0; + unsigned ind = 0; + while (totalBytes < (fMaxFluxFileMB * 1024 * 1024) && ind < allFiles.size()) { + selected.push_back(allFiles[order[ind]]); + totalBytes += allFiles[order[ind]].second; + ind++; + } + + // Copy files locally + auto localFiles = ifdhp->fetchSharedFiles(selected, fFluxCopyMethod); + + std::vector files(localFiles.size()); + for (unsigned i = 0; i < localFiles.size(); i++) { + files[i] = localFiles[i].first; + } + + return files; +} + +// ============================================================================ +// Load POT from metadata tree +// ============================================================================ + +double BNBKaonGenDK2NU::LoadPOT() +{ + TTreeReader metaReader(fMetaTreeName.c_str(), fFluxFile); + TTreeReaderValue pot(metaReader, "pots"); + + double total_pot = 0.; + while (metaReader.Next()) { + total_pot += *pot; + } + return total_pot; +} + +// ============================================================================ +// Return accumulated POT +// ============================================================================ + +double BNBKaonGenDK2NU::GetPOT() +{ + double ret = fAccumulatedPOT; + fAccumulatedPOT = 0.; + return ret; +} + +// ============================================================================ +// Unified GetNextEntry +// ============================================================================ + +void BNBKaonGenDK2NU::GetNextEntry() +{ + // Open new file if needed + if (fNewFile) { + + if (fFileIndex >= fFluxFiles.size()) { + fFileIndex = 0; + } + + if (fVerbose) { + std::cout << "New file: " << fFluxFiles[fFileIndex] + << " at index: " << fFileIndex + << " of: " << fFluxFiles.size() << std::endl; + } + + if (fFluxFile) delete fFluxFile; + fFluxFile = new TFile(fFluxFiles[fFileIndex].c_str()); + fFluxTree = (TTree*)fFluxFile->Get(fTreeName.c_str()); + + if (!fFluxTree) { + throw cet::exception("BNBKaonGenDK2NU") + << "Could not load tree " << fTreeName; + } + + // Initialize branches depending on mode + InitBranches(); + + // BooNE reader must be re-created per file + if (fFluxMode == "BooNE") { + if (fBooNe) delete fBooNe; + fBooNe = new bsim::BooNe(fFluxFiles[fFileIndex].c_str()); + } + + // Start at a random entry in this file + fEntryStart = CLHEP::RandFlat::shootInt( + fEngine, fFluxTree->GetEntries() - 1); + + fEntry = fEntryStart; + + // Load POT only for Dk2Nu mode + if (fFluxMode == "Dk2Nu") { + fThisFilePOT = LoadPOT(); + } + + fNewFile = false; + } + else { + fEntry = (fEntry + 1) % fFluxTree->GetEntries(); + + // If last entry was reached, move to next file + if ((fEntry + 1) % fFluxTree->GetEntries() == fEntryStart) { + fFileIndex++; + fNewFile = true; + } + } + + // Read current entry from ROOT tree + fFluxTree->GetEntry(fEntry); + + // Mode-dependent handling + if (fFluxMode == "BooNE") { + + fBooNe->myNtuple.run = fEntry; + fBooNe->myNtuple.eventn = fFileIndex; + fBooNe->GetEntry(fEntry); + + // Accumulate POT from BooNE + fAccumulatedPOT += fBooNe->GetPOT(); + } + else { + // Dk2Nu POT is evenly distributed per entry + fAccumulatedPOT += fThisFilePOT / fFluxTree->GetEntries(); + } +} + +// ============================================================================ +// Build MCFlux according to FluxMode +// ============================================================================ + +simb::MCFlux BNBKaonGenDK2NU::BuildMCFlux() +{ + if (fFluxMode == "BooNE") { + return MakeMCFlux(*fBooNe); + } + else { + return MakeMCFlux(*fDk2Nu); + } +} + +// ============================================================================ +// GetNext (public interface) +// ============================================================================ + +simb::MCFlux BNBKaonGenDK2NU::GetNext() +{ + GetNextEntry(); + return BuildMCFlux(); +} + +// ============================================================================ +// MakeMCFlux overloads +// ============================================================================ + +// --- BooNE version --- +simb::MCFlux BNBKaonGenDK2NU::MakeMCFlux(const bsim::BooNe &boone) +{ + simb::MCFlux flux; + auto fBooneNtp = boone.myNtuple; + + + + + if ( fBooneNtp.ntp == 1 ) { + flux.fntype = 12; //nue + } + else if ( fBooneNtp.ntp == 2 ) { + flux.fntype = -12; //nuebar + } + else if ( fBooneNtp.ntp == 3 ) { + flux.fntype = 14; //numu + } + else if ( fBooneNtp.ntp == 4 ) { + flux.fntype = -14; //numubar + } + else{ + mf::LogWarning("BooNEInterface") << "Neutrino type not recognized! ntp = " << fBooneNtp.ntp + << std::endl; + } + + flux.fFluxType = simb::kDk2Nu; + flux.fnimpwt = fBooneNtp.beamwgt; + flux.fvx = fBooneNtp.ini_pos[0][0]; //0 + flux.fvy = fBooneNtp.ini_pos[0][1]; //0 + flux.fvz = fBooneNtp.ini_pos[0][2]; //0 + flux.fpdpx = fBooneNtp.fin_mom[1][0]; //1 final + flux.fpdpy = fBooneNtp.fin_mom[1][1]; //1 final + flux.fpdpz = fBooneNtp.fin_mom[1][2]; //1 final + flux.fpppz = fBooneNtp.ini_mom[1][2]; //1 init + + // Momentum projected in dx/dz or dy/dz + flux.fpppz = fBooneNtp.ini_mom[1][2]; //1 init + double pppx = fBooneNtp.ini_mom[1][0]; //1 init + double pppy = fBooneNtp.ini_mom[1][1]; //1 init + double apppz = flux.fpppz; + if (TMath::Abs(flux.fpppz) < 1.0e-30) apppz = 1.0e-30; + flux.fppdxdz = pppx / apppz; + flux.fppdydz = pppy / apppz; + + flux.fppmedium = 0.; + flux.fppenergy = fBooneNtp.ini_eng[1]; + + int npart = fBooneNtp.npart; + int ptype_input = fBooneNtp.id[1]; + int tptype_input = fBooneNtp.id[npart-2]; + + if (ptype_input != 0) ptype_input = evgen::GeantToPdg(ptype_input); + if (tptype_input != 0) tptype_input= evgen::GeantToPdg(tptype_input); + + flux.fptype = ptype_input; + flux.ftptype = tptype_input; + + ///// + // Now need to calculate ndecay + ///// + + double Nenergy = fBooneNtp.ini_eng[0]; + double Ndxdz = fBooneNtp.ini_mom[0][0] / fBooneNtp.ini_mom[0][2]; + double Ndydz = fBooneNtp.ini_mom[0][1] / fBooneNtp.ini_mom[0][2]; + + double ppenergy = fBooneNtp.ini_eng[1]; + double pdPx = fBooneNtp.fin_mom[1][0]; + double pdPy = fBooneNtp.fin_mom[1][1]; + double pdPz = fBooneNtp.fin_mom[1][2]; + + double ppdxdz = fBooneNtp.ini_mom[1][0] / fBooneNtp.ini_mom[1][2]; + double ppdydz = fBooneNtp.ini_mom[1][1] / fBooneNtp.ini_mom[1][2]; + double pppz = fBooneNtp.ini_mom[1][2]; + + // Get the neutrino energy in the parent decay cm + double parent_mass = std::sqrt(ppenergy * ppenergy - + pppz * pppz * (ppdxdz * ppdxdz + + ppdydz * ppdydz + + 1.)); + + double parent_energy = std::sqrt(pdPx * pdPx + + pdPy * pdPy + + pdPz * pdPz + + parent_mass * parent_mass); + + double gamma = parent_energy / parent_mass; + double beta[3]; + beta[0] = pdPx / parent_energy; + beta[1] = pdPy / parent_energy; + beta[2] = pdPz / parent_energy; + + double partial = fBooneNtp.ini_mom[0][2] * gamma * + (beta[0] * Ndxdz + + beta[1] * Ndydz + + beta[2]); + + double Necm = gamma * Nenergy - partial; + + if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 1) flux.fndecay = 1; + else if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 2) flux.fndecay = 2; + else if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 3) flux.fndecay = 3; + else if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 4) flux.fndecay = 4; + else if (fBooneNtp.id[1] == 11 && fBooneNtp.ntp == 3) { + //check if it is a two or three body decay + if (fabs((parent_mass*parent_mass-0.105658389*0.105658389)/(2.*parent_mass)-Necm)/Necm <= 0.001) + //two body decay (numu + mu+) + flux.fndecay = 5; + else { + //three body decay (numu + pi0 + mu+) + flux.fndecay = 7; + } + } + else if (fBooneNtp.id[1] == 11 && fBooneNtp.ntp == 1) flux.fndecay = 6; + else if (fBooneNtp.id[1] == 12 && fBooneNtp.ntp == 4) { + if (fabs((parent_mass*parent_mass-0.105658389*0.105658389)/(2.*parent_mass)-Necm)/Necm <= 0.001) { + //two body decay (numu + mu+) + flux.fndecay = 8; + } + else { + //three body decay (numu + pi0 + mu+) + flux.fndecay = 10; + } + } + else if (fBooneNtp.id[1] == 12 && fBooneNtp.ntp == 2) flux.fndecay = 9; + else if (fBooneNtp.id[1] == 5 ) flux.fndecay = 11; + else if (fBooneNtp.id[1] == 6 ) flux.fndecay = 12; + else if (fBooneNtp.id[1] == 8 ) flux.fndecay = 13; + else if (fBooneNtp.id[1] == 9 ) flux.fndecay = 14; + + ///// + // End calculation of ndecay + ///// + double mupare; + double muparpx; + double muparpy; + double muparpz; + + if ( fBooneNtp.id[1] == 5 || fBooneNtp.id[1] == 6) { + mupare = fBooneNtp.ini_eng[2]; + muparpx = fBooneNtp.fin_mom[2][0]; + muparpy = fBooneNtp.fin_mom[2][1]; + muparpz = fBooneNtp.fin_mom[2][2]; + } else { + mupare = -9999.; + muparpx = -9999.; + muparpy = -9999.; + muparpz = -9999.; + } + + flux.fmuparpx = muparpx; + flux.fmuparpy = muparpy; + flux.fmuparpz = muparpz; + flux.fmupare = mupare; + + flux.fnecm = Necm; + + flux.fppvx = fBooneNtp.ini_pos[1][0]; + flux.fppvy = fBooneNtp.ini_pos[1][1]; + flux.fppvz = fBooneNtp.ini_pos[1][2]; + + flux.ftvx = fBooneNtp.ini_pos[npart-2][0]; + flux.ftvy = fBooneNtp.ini_pos[npart-2][1]; + flux.ftvz = fBooneNtp.ini_pos[npart-2][2]; + flux.ftpx = fBooneNtp.ini_mom[npart-2][0]; + flux.ftpy = fBooneNtp.ini_mom[npart-2][1]; + flux.ftpz = fBooneNtp.ini_mom[npart-2][2]; + // flux.ftgen = dk2nu.tgtexit.tgen; + + flux.frun = fBooneNtp.run; + flux.fevtno = fBooneNtp.eventn; + flux.ftgptype = evgen::GeantToPdg(fBooneNtp.id[npart-2]); + + // flux.fnenergyn = flux.fnenergyf = enu; + // flux.fnwtnear = flux.fnwtfar = wgt; + // ignore variables dealing with the neutrino + flux.fnenergyn = -1; + flux.fnwtnear = flux.fnwtfar = -1; + flux.fdk2gen = -1; + + // // placeholder for time + flux.fxpoint = fBooneNtp.ini_t[0]; + + return flux; +} + +// --- Dk2Nu version --- +simb::MCFlux BNBKaonGenDK2NU::MakeMCFlux(const bsim::Dk2Nu &dk2nu) +{ + simb::MCFlux flux; + + flux.fFluxType = simb::kDk2Nu; + flux.fntype = dk2nu.decay.ntype; + flux.fnimpwt = dk2nu.decay.nimpwt; + flux.fvx = dk2nu.decay.vx; + flux.fvy = dk2nu.decay.vy; + flux.fvz = dk2nu.decay.vz; + flux.fpdpx = dk2nu.decay.pdpx; + flux.fpdpy = dk2nu.decay.pdpy; + flux.fpdpz = dk2nu.decay.pdpz; + flux.fppdxdz = dk2nu.decay.ppdxdz; + flux.fppdydz = dk2nu.decay.ppdydz; + flux.fpppz = dk2nu.decay.pppz; + flux.fppenergy = dk2nu.decay.ppenergy; + flux.fppmedium = dk2nu.decay.ppmedium; + flux.fptype = dk2nu.decay.ptype; + flux.fndecay = dk2nu.decay.ndecay; + flux.fmuparpx = dk2nu.decay.muparpx; + flux.fmuparpy = dk2nu.decay.muparpy; + flux.fmuparpz = dk2nu.decay.muparpz; + flux.fmupare = dk2nu.decay.mupare; + flux.fnecm = dk2nu.decay.necm; + + flux.fppvx = dk2nu.ppvx; + flux.fppvy = dk2nu.ppvy; + flux.fppvz = dk2nu.ppvz; + + flux.ftvx = dk2nu.tgtexit.tvx; + flux.ftvy = dk2nu.tgtexit.tvy; + flux.ftvz = dk2nu.tgtexit.tvz; + flux.ftpx = dk2nu.tgtexit.tpx; + flux.ftpy = dk2nu.tgtexit.tpy; + flux.ftpz = dk2nu.tgtexit.tpz; + flux.ftptype = dk2nu.tgtexit.tptype; + flux.ftgen = dk2nu.tgtexit.tgen; + + flux.frun = dk2nu.job; + flux.fevtno = dk2nu.potnum; + flux.ftgptype = dk2nu.ancestor[1].pdg; + + // flux.fnenergyn = flux.fnenergyf = enu; + // flux.fnwtnear = flux.fnwtfar = wgt; + // ignore variables dealing with the neutrino + flux.fnenergyn = -1; + flux.fnwtnear = flux.fnwtfar = -1; + flux.fdk2gen = -1; + + // placeholder for time + flux.fxpoint = dk2nu.ancestor.back().startt; + + return flux; +} + +DEFINE_ART_CLASS_TOOL(BNBKaonGenDK2NU) + +} // namespace ldm +} // namespace evgen diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/BNBPi0Gen_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/BNBPi0Gen_tool.cc new file mode 100644 index 000000000..7b5c3feff --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/Tools/BNBPi0Gen_tool.cc @@ -0,0 +1,332 @@ +/** + * + */ + +// Framework Includes +#include "art/Framework/Core/EDProducer.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art/Persistency/Common/PtrMaker.h" +#include "art/Utilities/ToolMacros.h" +#include "cetlib/cpu_timer.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "CLHEP/Random/RandFlat.h" +#include "ifdh_art/IFDHService/IFDH_service.h" + +#include "nusimdata/SimulationBase/MCFlux.h" + +// local includes +#include "IMesonGen.h" + +// LArSoft includes +#include "dk2nu/tree/dk2nu.h" +#include "dk2nu/tree/dkmeta.h" +#include "dk2nu/tree/NuChoice.h" + +// ROOT +#include "TVector3.h" +#include "TTree.h" +#include "TFile.h" +#include "TTreeReader.h" +#include "TTreeReaderValue.h" + +// std includes +#include +#include +#include + +//------------------------------------------------------------------------------------------------------------------------------------------ +// implementation follows + +namespace evgen { +namespace ldm { +/** + * @brief BNBPi0Gen class definiton + */ +class BNBPi0Gen : public IMesonGen +{ +public: + /** + * @brief Constructor + */ + BNBPi0Gen(fhicl::ParameterSet const &pset); + + /** + * @brief Destructor + */ + ~BNBPi0Gen(); + + double GetPOT() override; + simb::MCFlux GetNext() override; + + void configure(const fhicl::ParameterSet&) override; + + const bsim::Dk2Nu *GetNextEntry(); + std::vector LoadFluxFiles(); + simb::MCFlux MakeMCFlux(const bsim::Dk2Nu &dk2nu); + double LoadPOT(); + + // no weights + double MaxWeight() override { return -1.; } + +private: + // config + std::string fSearchPath; + std::vector fSearchPatterns; + unsigned long fMaxFluxFileMB; + std::string fFluxCopyMethod; + bool fRandomizeFiles; + + std::string fTreeName; + std::string fMetaTreeName; + + // info for tracking files + unsigned fFileIndex; + bool fNewFile; + std::vector fFluxFiles; + + // info for tracking entry in file + unsigned fEntry; + unsigned fEntryStart; + + // ROOT Holders + TTree *fFluxTree; + TFile *fFluxFile; + bsim::Dk2Nu *fDk2Nu; + + // count POT + double fAccumulatedPOT; + double fThisFilePOT; + +}; + +BNBPi0Gen::BNBPi0Gen(fhicl::ParameterSet const &pset): + IMeVPrtlStage("BNBPi0Gen") +{ + configure(pset); + + // copy the flux files locally + fFluxFiles = LoadFluxFiles(); + + // setup indices + fFileIndex = 0; + fEntry = 0; + fEntryStart = 0; + fNewFile = true; + fFluxTree = NULL; + fFluxFile = NULL; + fDk2Nu = new bsim::Dk2Nu; + + fAccumulatedPOT = 0.; + fThisFilePOT = 0.; + +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +BNBPi0Gen::~BNBPi0Gen() +{ + + if (fDk2Nu) delete fDk2Nu; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +void BNBPi0Gen::configure(fhicl::ParameterSet const &pset) +{ + fSearchPath = pset.get("SearchPath"); + fSearchPatterns = pset.get>("FluxFiles"); + fMaxFluxFileMB = pset.get("MaxFluxFileMB", 2 * 1024); + fFluxCopyMethod = pset.get("FluxCopyMethod", "IFDH"); + fTreeName = pset.get("TreeName"); + fMetaTreeName = pset.get("MetaTreeName"); + fRandomizeFiles = pset.get("RandomizeFiles"); + + std::cout << "Searching for flux files at path: " << fSearchPath << std::endl; + std::cout << "With patterns:\n"; + for (const std::string &s: fSearchPatterns) std::cout << s << std::endl; + std::cout << "With copy method: " << fFluxCopyMethod << std::endl; +} + +std::vector BNBPi0Gen::LoadFluxFiles() { + art::ServiceHandle ifdhp; + + std::vector> allFiles; + + // find the flux files + for (unsigned i = 0; i < fSearchPatterns.size(); i++) { + std::vector> thisList = ifdhp->findMatchingFiles(fSearchPath, fSearchPatterns[i]); + std::copy (thisList.begin(), thisList.end(), std::back_inserter(allFiles)); + } + + // first randomize the flux files + std::vector order(allFiles.size(), 0); + if (fRandomizeFiles) { + std::vector rand(allFiles.size(), 0.); + CLHEP::RandFlat::shootArray(fEngine, rand.size(), &rand[0]); + TMath::Sort(allFiles.size(), &rand[0], &order[0], false); + } + else { + for (unsigned i = 0; i < order.size(); i++) { + order[i] = i; + } + } + + // If we are directly accessing the files, no need to copy + if (fFluxCopyMethod == "DIRECT") { + std::cout << "DIRECTLY ACCESSING FLUX FILES.\n"; + std::vector files(allFiles.size()); + for (unsigned i = 0; i < order.size(); i++) { + files[i] = allFiles[order[i]].first; + } + return files; + } + + // copy over up to the provided limit + std::vector> selected; + unsigned long totalBytes = 0; + unsigned ind = 0; + while (totalBytes < (fMaxFluxFileMB * 1024 * 1024) && ind < allFiles.size()) { + selected.push_back(allFiles[order[ind]]); + totalBytes += allFiles[order[ind]].second; + ind ++; + } + + // copy the files locally + std::vector> localFiles = ifdhp->fetchSharedFiles(selected, fFluxCopyMethod); + + std::vector files(localFiles.size()); + for (unsigned i = 0; i < localFiles.size(); i++) { + files[i] = localFiles[i].first; + } + + return files; +} + +double BNBPi0Gen::LoadPOT() { + TTreeReader metaReader(fMetaTreeName.c_str(), fFluxFile); + TTreeReaderValue pot(metaReader, "pots"); + + double total_pot = 0.; + + while (metaReader.Next()) { + total_pot += *pot; + } + + return total_pot; +} + + +double BNBPi0Gen::GetPOT() { + double ret = fAccumulatedPOT; + fAccumulatedPOT = 0.; + return ret; +} + +const bsim::Dk2Nu *BNBPi0Gen::GetNextEntry() { + // new file -- set the start entry + if (fNewFile) { + // wrap file index around + //if (fFileIndex >= fFluxFiles.size()) { + // fFileIndex = 0; + //} + if (fFileIndex >= fFluxFiles.size()) { + throw cet::exception("FluxReader Out of Files", + "At file index (" + std::to_string(fFileIndex) + ") of available files (" + std::to_string(fFluxFiles.size()) + ")."); + } + + std::cout << "New file: " << fFluxFiles[fFileIndex] << " at index: " << fFileIndex << " of: " << fFluxFiles.size() << std::endl; + if (fFluxFile) delete fFluxFile; + fFluxFile = new TFile(fFluxFiles[fFileIndex].c_str()); + fFluxTree = (TTree*)fFluxFile->Get(fTreeName.c_str()); + fFluxTree->SetBranchAddress("dk2nu",&fDk2Nu); + + // Start at a random index in this file + fEntryStart = CLHEP::RandFlat::shootInt(fEngine, fFluxTree->GetEntries()-1); + fEntry = fEntryStart; + + // load the POT in this file + fThisFilePOT = LoadPOT(); + fNewFile = false; + } + else { + fEntry = (fEntry + 1) % fFluxTree->GetEntries(); + // if this is the last entry, get ready for the next file + if ((fEntry + 1) % fFluxTree->GetEntries() == fEntryStart) { + fFileIndex ++; + fNewFile = true; + } + } + + // count the POT + fAccumulatedPOT += fThisFilePOT / fFluxTree->GetEntries(); + + fFluxTree->GetEntry(fEntry); + return fDk2Nu; +} + +simb::MCFlux BNBPi0Gen::GetNext() { + const bsim::Dk2Nu *flux = GetNextEntry(); + return MakeMCFlux(*flux); +} + +simb::MCFlux BNBPi0Gen::MakeMCFlux(const bsim::Dk2Nu &dk2nu) { + simb::MCFlux flux; + + flux.fFluxType = simb::kDk2Nu; + flux.fntype = -1; //dk2nu.decay.ntype; + flux.fnimpwt = dk2nu.decay.nimpwt; + flux.fvx = dk2nu.decay.vx; + flux.fvy = dk2nu.decay.vy; + flux.fvz = dk2nu.decay.vz; + flux.fpdpx = dk2nu.decay.pdpx; + flux.fpdpy = dk2nu.decay.pdpy; + flux.fpdpz = dk2nu.decay.pdpz; + flux.fppdxdz = dk2nu.decay.ppdxdz; + flux.fppdydz = dk2nu.decay.ppdydz; + flux.fpppz = dk2nu.decay.pppz; + flux.fppenergy = dk2nu.decay.ppenergy; + flux.fppmedium = dk2nu.decay.ppmedium; + flux.fptype = dk2nu.decay.ptype; + flux.fndecay = dk2nu.decay.ndecay; + flux.fmuparpx = dk2nu.decay.muparpx; + flux.fmuparpy = dk2nu.decay.muparpy; + flux.fmuparpz = dk2nu.decay.muparpz; + flux.fmupare = dk2nu.decay.mupare; + flux.fnecm = dk2nu.decay.necm; + + flux.fppvx = dk2nu.ppvx; + flux.fppvy = dk2nu.ppvy; + flux.fppvz = dk2nu.ppvz; + + flux.ftvx = dk2nu.tgtexit.tvx; + flux.ftvy = dk2nu.tgtexit.tvy; + flux.ftvz = dk2nu.tgtexit.tvz; + flux.ftpx = dk2nu.tgtexit.tpx; + flux.ftpy = dk2nu.tgtexit.tpy; + flux.ftpz = dk2nu.tgtexit.tpz; + flux.ftptype = dk2nu.tgtexit.tptype; + flux.ftgen = dk2nu.tgtexit.tgen; + + flux.frun = dk2nu.job; + flux.fevtno = dk2nu.potnum; + flux.ftgptype = dk2nu.ancestor[1].pdg; + + // flux.fnenergyn = flux.fnenergyf = enu; + // flux.fnwtnear = flux.fnwtfar = wgt; + // ignore variables dealing with the neutrino + flux.fnenergyn = -1; + flux.fnwtnear = flux.fnwtfar = -1; + flux.fdk2gen = -1; + + // placeholder for time + flux.fxpoint = dk2nu.ancestor.back().startt; + + return flux; +} + +DEFINE_ART_CLASS_TOOL(BNBPi0Gen) + +} // namespace ldm +} // namespace evgen diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/Constants.cpp b/sbncode/EventGenerator/MeVPrtl/Tools/Constants.cpp index 39d23b13d..2746dc4bf 100644 --- a/sbncode/EventGenerator/MeVPrtl/Tools/Constants.cpp +++ b/sbncode/EventGenerator/MeVPrtl/Tools/Constants.cpp @@ -22,7 +22,7 @@ Constants::Constants() { eta_mass = 0.547862; // GeV rho_mass = 0.77526; // GeV https://pdg.lbl.gov/2019/listings/rpp2019-list-rho-770.pdf etap_mass = 0.95778; // GeV - + gamma_mass = 0; // Couplings fine_structure_constant = 7.2973525693e-3;// https://pdg.lbl.gov/2019/reviews/rpp2019-rev-phys-constants.pdf Gfermi = 1.166379e-5; // 1/GeV^2 https://pdg.lbl.gov/2020/reviews/rpp2020-rev-phys-constants.pdf @@ -269,6 +269,8 @@ double PDG2Mass(int pdg) { return Constants::Instance().klong_mass; case 221: return Constants::Instance().eta_mass; + case 22: + return Constants::Instance().gamma_mass; case 11: case -11: return Constants::Instance().elec_mass; @@ -280,6 +282,8 @@ double PDG2Mass(int pdg) { case 15: case -15: return Constants::Instance().tau_mass; + case 111: + return Constants::Instance().pizero_mass; case 211: case -211: return Constants::Instance().piplus_mass; diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/Constants.h b/sbncode/EventGenerator/MeVPrtl/Tools/Constants.h index bcce6caa7..57421f71d 100644 --- a/sbncode/EventGenerator/MeVPrtl/Tools/Constants.h +++ b/sbncode/EventGenerator/MeVPrtl/Tools/Constants.h @@ -21,6 +21,7 @@ class Constants { public: // Masses + double gamma_mass; double elec_mass; double muon_mass; double piplus_mass; diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/CMakeLists.txt b/sbncode/EventGenerator/MeVPrtl/Tools/DP/CMakeLists.txt new file mode 100644 index 000000000..05bf7c003 --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/Tools/DP/CMakeLists.txt @@ -0,0 +1,108 @@ + +cet_build_plugin( PiZero2DPFlux art::tool + LIBRARIES + art::Framework_Core + art::Framework_Services_Registry + art_root_io::TFileService_service + art::Framework_Principal + art::Persistency_Common + art::Utilities canvas::canvas + cetlib::cetlib cetlib_except::cetlib_except + ROOT::EGPythia6 + CLHEP::CLHEP + sbnobj::Common_EventGen_MeVPrtl + nugen::EventGeneratorBase_GENIE + nusimdata::SimulationBase + nurandom::RandomUtils_NuRandomService_service + GSL::gsl + sbncode_EventGenerator_MeVPrtl_Constants + sbnobj::Common_EventGen_MeVPrtl +) + +cet_build_plugin( DPDecay art::tool + LIBRARIES + art::Framework_Core + art::Framework_Services_Registry + art_root_io::TFileService_service + art::Framework_Principal + art::Persistency_Common + art::Utilities canvas::canvas + cetlib::cetlib cetlib_except::cetlib_except + ROOT::EGPythia6 + CLHEP::CLHEP + sbnobj::Common_EventGen_MeVPrtl + nugen::EventGeneratorBase_GENIE + nusimdata::SimulationBase + nurandom::RandomUtils_NuRandomService_service + GSL::gsl + sbncode_EventGenerator_MeVPrtl_Constants + sbnobj::Common_EventGen_MeVPrtl +) +cet_build_plugin( Meson2DP art::tool + LIBRARIES + art::Framework_Core + art::Framework_Services_Registry + art_root_io::TFileService_service + art::Framework_Principal + art::Persistency_Common + art::Utilities canvas::canvas + cetlib::cetlib cetlib_except::cetlib_except + ROOT::EGPythia6 + CLHEP::CLHEP + sbnobj::Common_EventGen_MeVPrtl + nugen::EventGeneratorBase_GENIE + nusimdata::SimulationBase + nurandom::RandomUtils_NuRandomService_service + GSL::gsl + sbncode_EventGenerator_MeVPrtl_Constants + sbnobj::Common_EventGen_MeVPrtl +) + + +cet_build_plugin( Eta2DPFlux art::tool + LIBRARIES + art::Framework_Core + art::Framework_Services_Registry + art_root_io::TFileService_service + art::Framework_Principal + art::Persistency_Common + art::Utilities canvas::canvas + cetlib::cetlib cetlib_except::cetlib_except + CLHEP::CLHEP + nurandom::RandomUtils_NuRandomService_service + nusimdata::SimulationBase + GSL::gsl + larcorealg::Geometry + sbncode_EventGenerator_MeVPrtl_Dalitz + sbncode_EventGenerator_MeVPrtl_AnThreeBD + sbncode_EventGenerator_MeVPrtl_Constants + sbnobj::Common_EventGen_MeVPrtl + nugen::EventGeneratorBase_GENIE +) + +cet_build_plugin( DPMakeDecay art::tool + LIBRARIES + art::Framework_Core + art::Framework_Services_Registry + art_root_io::TFileService_service + art::Framework_Principal + art::Persistency_Common + art::Utilities canvas::canvas + cetlib::cetlib cetlib_except::cetlib_except + CLHEP::CLHEP + nurandom::RandomUtils_NuRandomService_service + nusimdata::SimulationBase + GSL::gsl + larcorealg::Geometry + sbncode_EventGenerator_MeVPrtl_Dalitz + sbncode_EventGenerator_MeVPrtl_AnThreeBD + sbncode_EventGenerator_MeVPrtl_AnTwoBD + sbncode_EventGenerator_MeVPrtl_Constants + sbnobj::Common_EventGen_MeVPrtl +) + +add_subdirectory(old) + +install_headers() +install_fhicl() +install_source() diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/DPDecay_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/DP/DPDecay_tool.cc new file mode 100644 index 000000000..6cef6f664 --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/Tools/DP/DPDecay_tool.cc @@ -0,0 +1,306 @@ + +#include "art/Utilities/ToolMacros.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" + +#include "sbncode/EventGenerator/MeVPrtl/Tools/IMeVPrtlDecay.h" +#include "sbncode/EventGenerator/MeVPrtl/Tools/Constants.h" +#include "sbnobj/Common/EventGen/MeVPrtl/MeVPrtlFlux.h" + +#include "CLHEP/Random/RandFlat.h" + +#include +#include +#include +#include +#include + +namespace evgen { +namespace ldm { + +namespace { + +double flat_to_exp_rand(double x, double mean, double a, double b) { + const double A = (1. - std::exp(-(b-a)/mean)); + return - mean * std::log(1 - x * A) + a; +} + +double forcedecay_weight(double mean, double a, double b) { + return std::exp(-a/mean) - std::exp(-b/mean); +} + + +} // anon + +class DPDecay : public IMeVPrtlDecay { +public: + DPDecay(fhicl::ParameterSet const& pset); + ~DPDecay() override = default; + + void configure(fhicl::ParameterSet const& pset) override; + + bool Decay(const MeVPrtlFlux& flux, + const TVector3& in, + const TVector3& out, + MeVPrtlDecay& decay, + double& weight) override; + + + double MaxWeight() override { return fMaxWeight; } + +private: + bool fAllowElectronDecay = true; + bool fAllowMuonDecay = true; + bool fAddTimeOfFlight = true; + bool fVerbose = false; + + // FHiCL inputs + // double fCTau_cm = 1.0; + // double fBR_ee = 1.0; + double fEpsilon = -1.0; + std::vector fMassGrid; + std::vector fBRHad; + std::vector fBRMu; + std::vector fBRE; + + double fReferenceRayLength = -1; + double fReferenceRayDistance = 0.; + double fReferenceMass = -1; + double fReferenceCTau_cm = -1; + double fReferenceEnergy = -1; + + double fMaxWeight = -1.; + double interp(const std::vector& x, + const std::vector& y, + double val) const; + + double Gamma_ll(double m, double eps, double ml) const; + + double Gamma_total(double m, double eps) const; + +}; + + auto load_table = [](const std::string& fname, + std::vector& m, + std::vector& br) { + std::ifstream f(fname); + double x, y; + while (f >> x >> y) { + m.push_back(x); + br.push_back(y); + } + }; + + +DPDecay::DPDecay(fhicl::ParameterSet const& pset) + : IMeVPrtlStage("DPDecay") +{ + configure(pset); +} + +void DPDecay::configure(fhicl::ParameterSet const& pset) +{ + fAllowElectronDecay = pset.get("AllowElectronDecay", true); + fAllowMuonDecay = pset.get("AllowMuonDecay", true); + fAddTimeOfFlight = pset.get("AddTimeOfFlight", true); + fVerbose = pset.get("Verbose", false); + fEpsilon = pset.get("Epsilon"); + //fCTau_cm = pset.get("CTau_cm"); + //fBR_ee = pset.get("BR_ee"); + + /* + if (fCTau_cm <= 0.0) { + throw cet::exception("DPDecay") << "CTau_cm must be > 0."; + } + fBR_ee = std::clamp(fBR_ee, 0.0, 1.0); +*/ + fReferenceRayLength = pset.get("ReferenceRayLength", -1.0); + fReferenceRayDistance = pset.get("ReferenceRayDistance", 0.0); + fReferenceMass = pset.get("ReferenceMass", -1.0); + fReferenceCTau_cm = pset.get("ReferenceCTau_cm", -1.0); + fReferenceEnergy = pset.get("ReferenceEnergy", -1.0); + + + load_table("bfrac_dark_photon_e_e.txt", fMassGrid, fBRE); + load_table("bfrac_dark_photon_mu_mu.txt", fMassGrid, fBRMu); + load_table("bfrac_dark_photon_hadrons.txt", fMassGrid, fBRHad); + + if (fReferenceRayLength > 0 && fReferenceMass > 0 && fReferenceCTau_cm > 0 && fReferenceEnergy > 0) { + const double mS = fReferenceMass; + + const double p = std::sqrt(std::max(0.0, fReferenceEnergy*fReferenceEnergy - mS*mS)); + const double gamma_beta = (mS > 0) ? (p / mS) : 0.0; + + const double mean_dist = fReferenceCTau_cm * gamma_beta; + if (mean_dist <= 0) { fMaxWeight = 0.0; return; } + + fMaxWeight = forcedecay_weight(mean_dist, fReferenceRayDistance, + fReferenceRayDistance + fReferenceRayLength); + } else { + fMaxWeight = -1.; + } +} + + double DPDecay::interp(const std::vector& x, + const std::vector& y, + double val) const { + int idx = 0; + double best = 1e9; + for (size_t i = 0; i < x.size(); i++) { + double d = std::abs(x[i] - val); + if (d < best) { best = d; idx = i; } + } + return y[idx]; + } + double DPDecay::Gamma_ll(double m, double eps, double ml) const { + const double alpha = 1.0/137.0; + if (m <= 2*ml) return 0.0; + + double beta = std::sqrt(1 - 4*ml*ml/(m*m)); + return (1.0/3.0) * alpha * eps*eps * m * + (1 + 2*ml*ml/(m*m)) * beta; + } + double DPDecay::Gamma_total(double m, double eps) const { + if (m < 0.29) { + return Gamma_ll(m, eps, 0.000511) + + Gamma_ll(m, eps, 0.105); + } else { + double br_mu = interp(fMassGrid, fBRMu, m); + double gmu = Gamma_ll(m, eps, 0.105); + return (br_mu > 0) ? gmu / br_mu : 0.0; + } + } + +bool DPDecay::Decay(const MeVPrtlFlux& flux, + const TVector3& in, + const TVector3& out, + MeVPrtlDecay& decay, + double& weight) +{ + const auto& C = Constants::Instance(); + + const double mS = flux.mass; + if (!(mS > 0.0)) return false; + + if (mS <= 2.0 * C.elec_mass) { + throw cet::exception("DPDecay") + << "BAD MASS: mS=" << mS << " below 2*me threshold."; + } + + /* + const bool ee_open = fAllowElectronDecay && (mS > 2.0*C.elec_mass); + const bool mumu_open = fAllowMuonDecay && (mS > 2.0*C.muon_mass); + + if (!ee_open && !mumu_open) return false; + + double br_e = 0.0; + double br_mu = 0.0; + + if (ee_open && mumu_open) { + br_e = fBR_ee; + br_mu = 1.0 - fBR_ee; + } else if (ee_open) { + // mu closed -> force ee + br_e = 1.0; + br_mu = 0.0; + } else { + // ee closed (shouldn't happen if mS>2me) -> force mu + br_e = 0.0; + br_mu = 1.0; + } + */ + // mean lab decay distance [cm] + // const double mean_dist = fCTau_cm * flux.mom.Gamma() * flux.mom.Beta(); + + const double mA = flux.mass; + const double Gamma = Gamma_total(mA, fEpsilon); + + double Gamma_ee = Gamma_ll(mA, fEpsilon, 0.000511); + double BR_ee = Gamma_ee / Gamma; + + if (Gamma <= 0) return false; + + // hbar*c in GeV*cm + const double hbarc = 1.973e-14; + + double ctau_cm = hbarc / Gamma; + + const double mean_dist = ctau_cm * flux.mom.Gamma() * flux.mom.Beta(); + if (mean_dist <= 0.0) return false; + + const double in_dist = (flux.pos.Vect() - in ).Mag(); + const double out_dist = (flux.pos.Vect() - out).Mag(); + + weight = forcedecay_weight(mean_dist, in_dist, out_dist); + weight *= BR_ee; + if (weight == 0.0) return false; + + + // pick channel by BR + /* const double u = CLHEP::RandFlat::shoot(fEngine, 0.0, 1.0); + const int ch = pick_by_br(br_e, br_mu, u); + if (ch < 0) return false; + */ + const int abs_pdg = 11; + const double ml = C.elec_mass; + + // sample decay point along ray within [in,out] + const double u2 = CLHEP::RandFlat::shoot(fEngine, 0.0, 1.0); + const double decay_rand = flat_to_exp_rand(u2, mean_dist, in_dist, out_dist); + TVector3 decay_pos3 = flux.pos.Vect() + decay_rand * (in - flux.pos.Vect()).Unit(); + + const double decay_time = fAddTimeOfFlight ? TimeOfFlight(flux, decay_pos3) : flux.pos.T(); + TLorentzVector decay_pos(decay_pos3, decay_time); + + // 2-body kinematics in S rest frame + const double E_rf = mS / 2.0; + const double p_rf = std::sqrt(std::max(0.0, E_rf*E_rf - ml*ml)); + + TVector3 pA_rf = RandomUnitVector() * p_rf; + TVector3 pB_rf = -pA_rf; + + TLorentzVector p4A(pA_rf, E_rf); + TLorentzVector p4B(pB_rf, E_rf); + + p4A.Boost(flux.mom.BoostVector()); + p4B.Boost(flux.mom.BoostVector()); + + + //const double tau_ns = fCTau_cm / C.c_cm_per_ns; + double tau_ns = (ctau_cm > 0) ? (ctau_cm / C.c_cm_per_ns) : 0.0; + const double gamma_tot = (tau_ns > 0) ? (C.hbar / tau_ns) : 0.0; + + decay.total_decay_width = gamma_tot; + decay.total_mean_lifetime = tau_ns; + decay.total_mean_distance = mean_dist; + decay.allowed_decay_fraction = 1.0; + + decay.pos = decay_pos; + + decay.daughter_mom.clear(); + decay.daughter_e.clear(); + decay.daughter_pdg.clear(); + + decay.daughter_mom.push_back(p4A.Vect()); + decay.daughter_e.push_back(p4A.E()); + decay.daughter_pdg.push_back(+abs_pdg); + + decay.daughter_mom.push_back(p4B.Vect()); + decay.daughter_e.push_back(p4B.E()); + decay.daughter_pdg.push_back(-abs_pdg); + + if (fVerbose) { + mf::LogInfo("DPDecay") + << "mS=" << mS + << " BR_ee(eff)=" << BR_ee + << " mean_dist_cm=" << mean_dist + << " weight=" << weight; + } + + return true; +} + +DEFINE_ART_CLASS_TOOL(DPDecay) + +} // namespace ldm +} // namespace evgen diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc new file mode 100644 index 000000000..e538cab44 --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc @@ -0,0 +1,204 @@ + + +#include "art/Utilities/ToolMacros.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" + +#include "sbncode/EventGenerator/MeVPrtl/Tools/IMeVPrtlFlux.h" +#include "sbnobj/Common/EventGen/MeVPrtl/MeVPrtlFlux.h" +#include "sbnobj/Common/EventGen/MeVPrtl/MesonParent.h" + +#include "TDatabasePDG.h" +#include "TParticlePDG.h" + +#include +#include +#include +#include + +namespace evgen { +namespace ldm { + +class Meson2DP : public IMeVPrtlFlux { +public: + Meson2DP(fhicl::ParameterSet const& pset); + ~Meson2DP() override = default; + + void configure(fhicl::ParameterSet const& pset) override; + bool MakeFlux(const simb::MCFlux& flux, MeVPrtlFlux& dp, double& weight) override; + + double MaxWeight() override { return 1.0; } + +private: + double fM = 0.0; + double fe = 0.0; + + bool fVerbose = false; + + std::vector fParents; + bool fCorrectDK2NU = true; + + std::string fSecondarySignConvention = "legacy"; // legacy/physical + + static double pdg_mass_GeV(int pdg) { + auto* db = TDatabasePDG::Instance(); + TParticlePDG* p = db->GetParticle(pdg); + return p ? p->Mass() : -1.0; + } + + static double BRMeson2SM(int pdg){ + + if (pdg == 221){ + return 0.39; + } + else if (pdg == 111){ + return 0.99; + } + return 0.0; + } + + static double BRMeson2DP(int pdg, double e, double mA){ + + double m_meson = pdg_mass_GeV(pdg); + double temp1 = 2*e*e; + double temp2 = 1-((mA*mA)/(m_meson*m_meson)); + double br = BRMeson2SM(pdg); + double br_dp = temp1*temp2*br; + + return br_dp; + + } + + static double twobody_momentum(double M, double m1, double m2) { + if (M < m1 + m2) return -1.0; + const double a = M*M - (m1+m2)*(m1+m2); + const double b = M*M - (m1-m2)*(m1-m2); + if (a < 0 || b < 0) return -1.0; + return std::sqrt(a*b) / (2.0*M); + } + + + bool parent_allowed(int abs_pdg) const { + for (int p : fParents) if (abs_pdg == std::abs(p)) return true; + return false; + } +}; + +Meson2DP::Meson2DP(fhicl::ParameterSet const& pset) + : IMeVPrtlStage("Meson2DP") + , IMeVPrtlFlux(pset) +{ + configure(pset); +} + +void Meson2DP::configure(fhicl::ParameterSet const& pset) +{ + fM = pset.get("M"); + fe = pset.get("e"); + + fVerbose = pset.get("Verbose", false); + + fParents = pset.get>("Parents", std::vector{321}); // default K± + fCorrectDK2NU = pset.get("CorrectDK2NU", true); + + fSecondarySignConvention = + pset.get("SecondarySignConvention", "legacy"); + std::transform(fSecondarySignConvention.begin(), fSecondarySignConvention.end(), + fSecondarySignConvention.begin(), ::tolower); +} + +bool Meson2DP::MakeFlux(const simb::MCFlux& flux, + evgen::ldm::MeVPrtlFlux& dp, + double& weight) +{ + evgen::ldm::MesonParent parent(flux); + + const int mpdg = parent.meson_pdg; + const int abs_mpdg = std::abs(mpdg); + + if (!parent_allowed(abs_mpdg)) return false; + + + if (abs_mpdg != 221) return false; // eta only + + const double mA = fM; + if (!(mA > 0.0)) return false; + + const double e = fe; + if (!(e > 0.0)) return false; + + + double br = BRMeson2DP(abs_mpdg, e, mA); + if (!(br > 0.0)) return false; + if (br > 1.0) { + if (fVerbose) mf::LogWarning("Meson2DP") << "BRprod>1 (" << br << "), capping to 1."; + br = 1.0; + } + + + TLorentzVector Beam4 = BeamOrigin(); + dp.pos_beamcoord = parent.pos; + dp.pos = parent.pos; + dp.pos.Transform(fBeam2Det); + dp.pos += Beam4; + + dp.mmom_beamcoord = parent.mom; + dp.mmom = parent.mom; + dp.mmom.Transform(fBeam2Det); + + + const int gamma_pdg = 22; + + const double mPi0 = pdg_mass_GeV(221); + const double mgamma = 0.0; + + const double pstar = twobody_momentum(mPi0, mgamma, mA); + if (pstar < 0) return false; + + const double eA = std::sqrt(pstar*pstar + mA*mA); + + // isotropic S in K rest frame + dp.mom = TLorentzVector(pstar * RandomUnitVector(), eA); + + // boost to lab + TLorentzVector mom_lab = dp.mom; + mom_lab.Boost(parent.mom.BoostVector()); + + dp.mom_beamcoord = mom_lab; + dp.mom = mom_lab; + dp.mom.Transform(fBeam2Det); + + dp.sec_beamcoord = dp.mmom_beamcoord - dp.mom_beamcoord; + dp.sec = dp.mmom - dp.mom; + + double denom = 1.0; + + weight = parent.weight * br / denom; + if (weight == 0.0) return false; + + dp.mass = mA; + dp.meson_pdg = mpdg; + dp.secondary_pdg = gamma_pdg; + + dp.generator = 1; + dp.equiv_enu = EnuLab(flux.fnecm, dp.mmom, dp.pos); + + + dp.C1 = 0.0; dp.C2 = 0.0; dp.C3 = 0.0; dp.C4 = 0.0; dp.C5 = 0.0; + + if (fVerbose) { + mf::LogInfo("Meson2DP") + << "parent=" << mpdg + << " mA=" << mA + << " BRprod=" << br + << " denom=" << denom + << " weight=" << weight; + } + + return true; +} + +DEFINE_ART_CLASS_TOOL(Meson2DP) + +} // namespace ldm +} // namespace evgen diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/CMakeLists.txt b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/CMakeLists.txt new file mode 100644 index 000000000..04344c706 --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/CMakeLists.txt @@ -0,0 +1,107 @@ + +cet_build_plugin( PiZero2DPFlux art::tool + LIBRARIES + art::Framework_Core + art::Framework_Services_Registry + art_root_io::TFileService_service + art::Framework_Principal + art::Persistency_Common + art::Utilities canvas::canvas + cetlib::cetlib cetlib_except::cetlib_except + ROOT::EGPythia6 + CLHEP::CLHEP + sbnobj::Common_EventGen_MeVPrtl + nugen::EventGeneratorBase_GENIE + nusimdata::SimulationBase + nurandom::RandomUtils_NuRandomService_service + GSL::gsl + sbncode_EventGenerator_MeVPrtl_Constants + sbnobj::Common_EventGen_MeVPrtl +) + +cet_build_plugin( ScalarDecayKevin art::tool + LIBRARIES + art::Framework_Core + art::Framework_Services_Registry + art_root_io::TFileService_service + art::Framework_Principal + art::Persistency_Common + art::Utilities canvas::canvas + cetlib::cetlib cetlib_except::cetlib_except + ROOT::EGPythia6 + CLHEP::CLHEP + sbnobj::Common_EventGen_MeVPrtl + nugen::EventGeneratorBase_GENIE + nusimdata::SimulationBase + nurandom::RandomUtils_NuRandomService_service + GSL::gsl + sbncode_EventGenerator_MeVPrtl_Constants + sbnobj::Common_EventGen_MeVPrtl +) +cet_build_plugin( Meson2ScalarKevin art::tool + LIBRARIES + art::Framework_Core + art::Framework_Services_Registry + art_root_io::TFileService_service + art::Framework_Principal + art::Persistency_Common + art::Utilities canvas::canvas + cetlib::cetlib cetlib_except::cetlib_except + ROOT::EGPythia6 + CLHEP::CLHEP + sbnobj::Common_EventGen_MeVPrtl + nugen::EventGeneratorBase_GENIE + nusimdata::SimulationBase + nurandom::RandomUtils_NuRandomService_service + GSL::gsl + sbncode_EventGenerator_MeVPrtl_Constants + sbnobj::Common_EventGen_MeVPrtl +) + + +cet_build_plugin( Eta2DPFlux art::tool + LIBRARIES + art::Framework_Core + art::Framework_Services_Registry + art_root_io::TFileService_service + art::Framework_Principal + art::Persistency_Common + art::Utilities canvas::canvas + cetlib::cetlib cetlib_except::cetlib_except + CLHEP::CLHEP + nurandom::RandomUtils_NuRandomService_service + nusimdata::SimulationBase + GSL::gsl + larcorealg::Geometry + sbncode_EventGenerator_MeVPrtl_Dalitz + sbncode_EventGenerator_MeVPrtl_AnThreeBD + sbncode_EventGenerator_MeVPrtl_Constants + sbnobj::Common_EventGen_MeVPrtl + nugen::EventGeneratorBase_GENIE +) + +cet_build_plugin( DPMakeDecay art::tool + LIBRARIES + art::Framework_Core + art::Framework_Services_Registry + art_root_io::TFileService_service + art::Framework_Principal + art::Persistency_Common + art::Utilities canvas::canvas + cetlib::cetlib cetlib_except::cetlib_except + CLHEP::CLHEP + nurandom::RandomUtils_NuRandomService_service + nusimdata::SimulationBase + GSL::gsl + larcorealg::Geometry + sbncode_EventGenerator_MeVPrtl_Dalitz + sbncode_EventGenerator_MeVPrtl_AnThreeBD + sbncode_EventGenerator_MeVPrtl_AnTwoBD + sbncode_EventGenerator_MeVPrtl_Constants + sbnobj::Common_EventGen_MeVPrtl +) + + +install_headers() +install_fhicl() +install_source() diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/DPMakeDecay_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/DPMakeDecay_tool.cc new file mode 100644 index 000000000..58cdeff0c --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/DPMakeDecay_tool.cc @@ -0,0 +1,239 @@ +/** + * Dark Photon Decay Tool + */ + +#include "art/Framework/Core/EDProducer.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art/Persistency/Common/PtrMaker.h" +#include "art/Utilities/ToolMacros.h" +#include "cetlib/cpu_timer.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" + + +#include "sbnobj/Common/EventGen/MeVPrtl/MeVPrtlFlux.h" +#include "sbncode/EventGenerator/MeVPrtl/Tools/IMeVPrtlDecay.h" +#include "sbncode/EventGenerator/MeVPrtl/Tools/Constants.h" + +#include "CLHEP/Random/RandFlat.h" +#include "TDatabasePDG.h" + +#include +#include +#include +#include + +namespace evgen { + namespace ldm { + + class DPMakeDecay : public IMeVPrtlDecay { + + public: + DPMakeDecay(fhicl::ParameterSet const &pset); + ~DPMakeDecay() {} + + void configure(fhicl::ParameterSet const &pset) override; + + bool Decay(const MeVPrtlFlux &flux, + const TVector3 &in, + const TVector3 &out, + MeVPrtlDecay &decay, + double &weight) override; + + double MaxWeight() override { return 1.0; } + + private: + + double fEpsilon; + bool fVerbose; + + std::vector fMassBR; + std::vector fBRElec; + std::vector fBRHad; + std::vector fBRMu; + + double AlphaEM() const { return 1.0/137.0; } + + double GammaLL(double m, double mlep) const { + if (m <= 2*mlep) return 0.0; + + double coupsq = fEpsilon*fEpsilon*AlphaEM(); + return (coupsq/3.0)*m* + (1 + 2*mlep*mlep/(m*m))* + std::sqrt(1 - 4*mlep*mlep/(m*m)); + } + + double InterpBR(const std::vector& mass, + const std::vector& br, + double m) const { + + if (mass.empty()) return 0.0; + + size_t best = 0; + double mindiff = std::abs(mass[0] - m); + + for (size_t i=1;i 0) + return gamma_mu / br_mu; + + return GammaLL(m, me); + } + + }; + + DPMakeDecay::DPMakeDecay(fhicl::ParameterSet const &pset) + : IMeVPrtlStage("DPMakeDecay") + { + configure(pset); + } + + void DPMakeDecay::configure(fhicl::ParameterSet const &pset) + { + fVerbose = pset.get("Verbose", false); + fEpsilon = pset.get("Epsilon"); + + std::string file_ee = "/pnfs/sbnd/persistent/users/rohanr/dp/br/bfrac_dark_photon_e_e.txt"; + std::string file_had = "/pnfs/sbnd/persistent/users/rohanr/dp/br/bfrac_dark_photon_hadrons.txt"; + std::string file_mu = "/pnfs/sbnd/persistent/users/rohanr/dp/br/bfrac_dark_photon_mu_mu.txt"; + + std::ifstream eefile(file_ee); + std::ifstream hadfile(file_had); + std::ifstream mufile(file_mu); + + double m, br; + + while (eefile >> m >> br) { + fMassBR.push_back(m); + fBRElec.push_back(br); + } + + while (hadfile >> m >> br) { + fMassBR.push_back(m); + fBRHad.push_back(br); + } + + while (mufile >> m >> br) { + fBRMu.push_back(br); + } + + if (fVerbose) + std::cout << "Loaded Dark Photon BR tables." << std::endl; + } + + bool DPMakeDecay::Decay(const MeVPrtlFlux &flux, + const TVector3 &in, + const TVector3 &out, + MeVPrtlDecay &decay, + double &weight) + { + double m = flux.mass; + + double total_width = TotalWidth(m); + if (total_width == 0) return false; + + double lifetime_ns = Constants::Instance().hbar / total_width; + double mean_dist = lifetime_ns * + flux.mom.Gamma() * + flux.mom.Beta() * + Constants::Instance().c_cm_per_ns; + + double in_dist = (flux.pos.Vect() - in).Mag(); + double out_dist = (flux.pos.Vect() - out).Mag(); + + double forced_weight = + std::exp(-in_dist/mean_dist) - + std::exp(-out_dist/mean_dist); + + weight = forced_weight; + + if (weight <= 0) return false; + + double me = Constants::Instance().elec_mass; + // double mmu = Constants::Instance().muon_mass; + + /* + double gamma_ee = GammaLL(m, me); + double gamma_mumu = GammaLL(m, mmu); + + double r = CLHEP::RandFlat::shoot(fEngine); + + bool decay_to_mu = false; + if (gamma_mumu > 0 && + r < gamma_mumu / total_width) + decay_to_mu = true; + + double mlep = decay_to_mu ? mmu : me; + int pdg = decay_to_mu ? 13 : 11; + */ + + double gamma_ee = GammaLL(m, me); + + double br_ee = gamma_ee / total_width; + weight *= br_ee; + + double mlep = me; + int pdg = 11; + double p = std::sqrt(m*m/4. - mlep*mlep); + + TVector3 dir = RandomUnitVector(); + + TLorentzVector lplus( p*dir, std::sqrt(p*p + mlep*mlep) ); + TLorentzVector lminus(-p*dir, std::sqrt(p*p + mlep*mlep) ); + + lplus.Boost(flux.mom.BoostVector()); + lminus.Boost(flux.mom.BoostVector()); + + double flat = CLHEP::RandFlat::shoot(fEngine,0,1); + double decay_dist = -mean_dist*std::log(1-flat); + + TVector3 decay_pos = + flux.pos.Vect() + + decay_dist * (in - flux.pos.Vect()).Unit(); + + decay.pos = TLorentzVector(decay_pos, + TimeOfFlight(flux, decay_pos)); + + decay.daughter_mom.push_back(lplus.Vect()); + decay.daughter_e.push_back(lplus.E()); + decay.daughter_pdg.push_back(-pdg); + + decay.daughter_mom.push_back(lminus.Vect()); + decay.daughter_e.push_back(lminus.E()); + decay.daughter_pdg.push_back(pdg); + + decay.total_decay_width = total_width; + decay.total_mean_lifetime = lifetime_ns; + decay.total_mean_distance = mean_dist; + decay.allowed_decay_fraction = 1.0; + + return true; + } + + DEFINE_ART_CLASS_TOOL(DPMakeDecay) + + } // namespace ldm +} // namespace evgen diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/Eta2DPFlux_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/Eta2DPFlux_tool.cc new file mode 100644 index 000000000..e807663d3 --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/Eta2DPFlux_tool.cc @@ -0,0 +1,231 @@ +/** + * + */ + +// Framework Includes +#include "art/Framework/Core/EDProducer.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art/Persistency/Common/PtrMaker.h" +#include "art/Utilities/ToolMacros.h" +#include "cetlib/cpu_timer.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "CLHEP/Random/RandFlat.h" + +// local includes +#include "sbncode/EventGenerator/MeVPrtl/Tools/IMeVPrtlFlux.h" +#include "sbncode/EventGenerator/MeVPrtl/Tools/Constants.h" + +#include "sbnobj/Common/EventGen/MeVPrtl/MeVPrtlFlux.h" +#include "sbnobj/Common/EventGen/MeVPrtl/MesonParent.h" + +// ROOT +#include "TVector3.h" + +// std includes +#include +#include +#include + +#include "TDatabasePDG.h" + +//------------------------------------------------------------------------------------------------------------------------------------------ +// implementation follows + +namespace evgen { +namespace ldm { +/** + * @brief Tau2HNLFlux class definiton + * + * Implementation of Kaon->HNL branching ratio taken from: + * arXiv:1912.07622 + */ +class Tau2HNLFlux : public IMeVPrtlFlux +{ +public: + /** + * @brief Constructor + */ + Tau2HNLFlux(fhicl::ParameterSet const &pset); + + /** + * @brief Destructor + */ + ~Tau2HNLFlux(); + + bool MakeFlux(const simb::MCFlux &flux, MeVPrtlFlux &hnl, double &weight) override; + void configure(const fhicl::ParameterSet&) override; + + double MaxWeight() override; + +private: + // config + double fM; //!< Mass of HNL [GeV] + double fMagUt4; +}; + +Tau2HNLFlux::Tau2HNLFlux(fhicl::ParameterSet const &pset): + IMeVPrtlStage("Tau2HNLFlux"), + IMeVPrtlFlux(pset) +{ + this->configure(pset); + +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +Tau2HNLFlux::~Tau2HNLFlux() +{ +} + +// helper functions +// +// tau -> pi + HNL +double hnl_momentum(double tau_mass, double pion_mass, double hnl_mass) { + if (tau_mass - pion_mass < hnl_mass) return -1.; + + return sqrt(tau_mass * tau_mass * tau_mass * tau_mass + -2 * tau_mass * tau_mass * pion_mass * pion_mass + -2 * tau_mass * tau_mass * hnl_mass * hnl_mass + + pion_mass * pion_mass * pion_mass * pion_mass + + hnl_mass * hnl_mass * hnl_mass * hnl_mass + -2 * pion_mass * pion_mass * hnl_mass * hnl_mass) / ( 2 * tau_mass ); +} + +/* Polarization of a HNL emerging from a two body meson decay (M-> l N) + m_l is the mass of the lepton and m_M the mass of the parent meson + See arXiv:2109.10358 for more details. + Due to crossing symmetry the polarization of the tau -> m N gives the same result */ +double PolHNL(double m_HNL, double m_l, double m_M) +{ + double yl = m_l / m_M; + double yHNL = m_HNL / m_M; + double numterm = (yl*yl - yHNL * yHNL) * sqrt(pow(yHNL,4) + (1.0 - yl * yl)*(1.0 - yl * yl) - 2.0 * yHNL * yHNL * (1.0 + yl * yl)); + double denterm = pow(yl,4) + pow(yHNL,4) - 2.0 * yl * yl * yHNL * yHNL - yl * yl - yHNL * yHNL; + return numterm / denterm; +} + +double BranchingRatio(double hnl_mass, double u4) { + double Gfermi = Constants::Instance().Gfermi; + double Vud2 = Constants::Instance().abs_Vud_squared; + double fpion = Constants::Instance().fpion; + double tau_mass = Constants::Instance().tau_mass; + double tau_lifetime = Constants::Instance().tau_lifetime; + double pi_mass = Constants::Instance().piplus_mass; + double hbar = Constants::Instance().hbar; + + double coupling = 0.9*tau_lifetime*u4*Gfermi*Gfermi*Vud2*fpion*fpion*tau_mass*tau_mass*tau_mass / (16*M_PI) / hbar; + + double hnl_mass2 = hnl_mass*hnl_mass; + double tau_mass2 = tau_mass*tau_mass; + double pi_mass2 = pi_mass*pi_mass; + + double kinematic_factor = \ + ((1 - hnl_mass2 / tau_mass2) * (1 - hnl_mass2 / tau_mass2) \ + - (pi_mass2 / tau_mass2) * (1 + hnl_mass2 / tau_mass2)) \ + *sqrt((1 - (pi_mass - hnl_mass)*(pi_mass - hnl_mass)/tau_mass2)*(1 - (hnl_mass+pi_mass)*(hnl_mass+pi_mass)/tau_mass2)); + + return coupling * kinematic_factor; +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +void Tau2HNLFlux::configure(fhicl::ParameterSet const &pset) +{ + fM = pset.get("M"); + fMagUt4 = pset.get("MagUt4"); + + double max_mass = Constants::Instance().tau_mass - Constants::Instance().piplus_mass; + + if (fM > max_mass) { + throw cet::exception("Tau2HNLFlux Tool: BAD MASS. Configured mass (" + std::to_string(fM) + + ") is larger than maximum allowed by enabled couplings (" + std::to_string(max_mass) + ")."); + } + +} + +double Tau2HNLFlux::MaxWeight() { + return BranchingRatio(fM, fMagUt4); +} + +bool Tau2HNLFlux::MakeFlux(const simb::MCFlux &flux, evgen::ldm::MeVPrtlFlux &hnl, double &weight) { + // make the tau parent + evgen::ldm::MesonParent tau(flux); + if (abs(tau.meson_pdg) != 15) return false; // Only take taus + + TLorentzVector Beam4 = BeamOrigin(); + + // get position in detector frame + hnl.pos_beamcoord = tau.pos; + hnl.pos = tau.pos; + hnl.pos.Transform(fBeam2Det); + hnl.pos += Beam4; + + double br = BranchingRatio(fM, fMagUt4); + + std::cout << "BR: " << br << std::endl; + + // ignore if we can't make this hnl + // Ignore if branching ratio is exactly 0. + if (br == 0.) return false; + + // get the momentum direction in the tau parent rest frame + double p = hnl_momentum(Constants::Instance().tau_mass, Constants::Instance().piplus_mass, fM); + double e = sqrt(p*p + fM * fM); + // Two-body decays are isotropic + hnl.mom = TLorentzVector(p*RandomUnitVector(), e); + + // boost to lab frame + TLorentzVector mom = hnl.mom; + mom.Boost(tau.mom.BoostVector()); + + hnl.mom_beamcoord = mom; + // rotate to detector frame + hnl.mom = mom; + hnl.mom.Transform(fBeam2Det); + + hnl.mmom_beamcoord = tau.mom; + // also save the tau momentum in the detector frame + hnl.mmom = tau.mom; + hnl.mmom.Transform(fBeam2Det); + + // and save the secondary momentum + hnl.sec = hnl.mmom - hnl.mom; + hnl.sec_beamcoord = hnl.mmom_beamcoord - hnl.mom_beamcoord; + + // The weight is the importance weight times the branching-ratio weight + weight = tau.weight * br; + + // set the mixing + hnl.C1 = 0.; + hnl.C2 = 0.; + hnl.C3 = fMagUt4; + hnl.mass = fM; + + hnl.meson_pdg = tau.meson_pdg; + hnl.secondary_pdg = 211 * (tau.meson_pdg > 0 ? 1 : -1); + hnl.generator = 1; // kHNL + + // equivalent neutrino energy -- doesn't apply here + hnl.equiv_enu = -1; + + +// Get the HNL Polarization + double meson_mass = Constants::Instance().kplus_mass; + if(abs(hnl.meson_pdg) == 321) { + meson_mass = Constants::Instance().kplus_mass; + }else if(abs(hnl.meson_pdg) == 211) { + meson_mass = Constants::Instance().piplus_mass; + } + + + hnl.polarization = PolHNL(fM , Constants::Instance().tau_mass, meson_mass); + + return true; +} + +DEFINE_ART_CLASS_TOOL(Tau2HNLFlux) + +} // namespace ldm +} // namespace evgen diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/PiZero2DPFlux_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/PiZero2DPFlux_tool.cc new file mode 100644 index 000000000..e8d2224f2 --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/PiZero2DPFlux_tool.cc @@ -0,0 +1,275 @@ +/** + * + */ + +// Framework Includes +#include "art/Framework/Core/EDProducer.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art/Persistency/Common/PtrMaker.h" +#include "art/Utilities/ToolMacros.h" +#include "cetlib/cpu_timer.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "CLHEP/Random/RandFlat.h" + +// local includes +#include "sbncode/EventGenerator/MeVPrtl/Tools/IMeVPrtlFlux.h" +#include "sbncode/EventGenerator/MeVPrtl/Tools/Constants.h" + +#include "sbnobj/Common/EventGen/MeVPrtl/MeVPrtlFlux.h" +#include "sbnobj/Common/EventGen/MeVPrtl/MesonParent.h" + +// ROOT +#include "TVector3.h" + +// std includes +#include +#include +#include + +#include "TDatabasePDG.h" + +//------------------------------------------------------------------------------------------------------------------------------------------ +// implementation follows + +namespace evgen { +namespace ldm { +/** + * @brief PiZero2DPFlux class definiton + * + * Implementation of Kaon->DP branching ratio taken from: + * arXiv:1912.07622 + */ +class PiZero2DPFlux : public IMeVPrtlFlux +{ +public: + /** + * @brief Constructor + */ + PiZero2DPFlux(fhicl::ParameterSet const &pset); + + /** + * @brief Destructor + */ + ~PiZero2DPFlux(); + + bool MakeFlux(const simb::MCFlux &flux, MeVPrtlFlux &dp, double &weight) override; + void configure(const fhicl::ParameterSet&) override; + + double MaxWeight() override; + +private: + // config + double fM; //!< Mass of DP [GeV] + double fe; + double fTarget2Absorber; + double Pi0ToDPBR(double mA) const; +}; + +PiZero2DPFlux::PiZero2DPFlux(fhicl::ParameterSet const &pset): + IMeVPrtlStage("PiZero2DPFlux"), + IMeVPrtlFlux(pset) +{ + this->configure(pset); + +} + +//------------------------------------------------------------------------------------------------------------------------------------------ + +PiZero2DPFlux::~PiZero2DPFlux() +{ +} + +// helper functions +// +// pi0 -> photon + DP +double dp_momentum(double pi0_mass, double gamma_mass, double dp_mass) { + if (pi0_mass - gamma_mass < dp_mass) return -1.; + + return sqrt(pi0_mass * pi0_mass * pi0_mass * pi0_mass + -2 * pi0_mass * pi0_mass * gamma_mass * gamma_mass + -2 * pi0_mass * pi0_mass * dp_mass * dp_mass + + gamma_mass * gamma_mass * gamma_mass * gamma_mass + + dp_mass * dp_mass * dp_mass * dp_mass + -2 * gamma_mass * gamma_mass * dp_mass * dp_mass) / ( 2 * pi0_mass ); +} + + +double SMKaonBR(int pi0_pdg) { + // The Kaons in Dk2nu file only include those that decay to neutrinos. + // + // We want all kaons -- in order to account for this, we divide by the + // branching-ratio of kaons to neutrinos + // + // Taken from: + // /cvmfs/minerva.opensciencegrid.org/minerva/beamsim/x86_64/geant4/source/particles/hadrons/mesons/src/G4KaonPlus.cc + // /cvmfs/minerva.opensciencegrid.org/minerva/beamsim/x86_64/geant4/source/particles/hadrons/mesons/src/G4KaonZerLong.cc + switch (pi0_pdg) { + case 321: + return 0.6339 /* 5 */ + 0.0559 /* 6 */ + 0.0330 /* 7 */; + case -321: + return 0.6339 /* 8 */ + 0.0559 /* 9 */ + 0.0330 /* 10 */; + case 130: + return 0.2020 /* 1 */ + 0.2020 /* 2 */ + 0.1348 /* 3 */ + 0.1348 /* 4 */; + default: + return -1; + } +} + +double BranchingRatio(double dp_mass, double u4, bool is_muon) { + double lep_mass = is_muon ? Constants::Instance().muon_mass : Constants::Instance().elec_mass; + double kplus_mass = Constants::Instance().kplus_mass; + + if (dp_mass > kplus_mass - lep_mass) return 0.; + + double smbr = is_muon ? Constants::Instance().kaonp_mup_numu : Constants::Instance().kaonp_ep_nue; + double lep_ratio = (lep_mass * lep_mass) / (kplus_mass * kplus_mass); + double dp_ratio = (dp_mass * dp_mass) / (kplus_mass * kplus_mass); + double kinematic_factor = (lep_ratio + dp_ratio - (lep_ratio - dp_ratio) * (lep_ratio - dp_ratio)) \ + * sqrt(1 + dp_ratio * dp_ratio + lep_ratio * lep_ratio - 2*(dp_ratio + lep_ratio + dp_ratio*lep_ratio)) \ + / (lep_ratio * (1. - lep_ratio) * (1. - lep_ratio)); + + // scale the branching ratio + return smbr * (u4 / (1. - u4)) * kinematic_factor; +} + +std::pair Branch(double dp_mass, double ue4, double um4, double rand) { + double kplus_mass = Constants::Instance().kplus_mass; + + double br_muon = (um4 > 0. && dp_mass < kplus_mass - Constants::Instance().muon_mass) ? BranchingRatio(dp_mass, um4, true) : 0.; + double br_elec = (ue4 > 0. && dp_mass < kplus_mass - Constants::Instance().elec_mass) ? BranchingRatio(dp_mass, ue4, false): 0.; + if (br_muon == 0. && br_elec == 0.) return {0., false}; + + double br_weight = br_muon + br_elec; + + bool is_muon = rand < (br_muon / br_weight); + + return {br_weight, is_muon}; +} + + double PiZero2DPFlux::Pi0ToDPBR(double mA) const { + + double mpi0 = Constants::Instance().pizero_mass; + double br_gammagamma = 0.988; // PDG value + + if (mA >= mpi0) return 0.0; + + double factor = 1.0 - (mA * mA) / (mpi0 * mpi0); + return 2.0 * fe * fe * std::pow(factor, 3) * br_gammagamma; + } + +//------------------------------------------------------------------------------------------------------------------------------------------ +void PiZero2DPFlux::configure(fhicl::ParameterSet const &pset) +{ + fM = pset.get("M"); + fe = pset.get("e"); + // fMagUm4 = pset.get("MagUm4"); + // fMagUe4 = pset.get("MagUe4"); + + fTarget2Absorber = pset.get("Target2Absorber", 5000); + // fKDAROnly = pset.get("KDAROnly", false); + /* + double max_mass = (fMagUe4 > 0.) ? (Constants::Instance().kplus_mass - Constants::Instance().elec_mass) : + (Constants::Instance().kplus_mass - Constants::Instance().muon_mass); + + if (fM > max_mass) { + throw cet::exception("PiZero2DPFlux Tool: BAD MASS. Configured mass (" + std::to_string(fM) + + ") is larger than maximum allowed by enabled couplings (" + std::to_string(max_mass) + ")."); + } + */ +} + +double PiZero2DPFlux::MaxWeight() { + // Weight comes from the NuMi importance weight -- max is 100 (add in an epsilon) + // Scale by the branching ratios here + // return 100.0001 * std::max(BranchingRatio(fM, fMagUe4, false) / SMKaonBR(321), BranchingRatio(fM, fMagUm4, true) / SMKaonBR(321)); + return 1; +} + +bool PiZero2DPFlux::MakeFlux(const simb::MCFlux &flux, evgen::ldm::MeVPrtlFlux &dp, double &weight) { + // make the pi0 parent + evgen::ldm::MesonParent kaon(flux); + if (abs(kaon.meson_pdg) != 111) return false; // Only take charged kaons + double mpi0 = Constants::Instance().pizero_mass; + TLorentzVector Beam4 = BeamOrigin(); + + // get position in detector frame + dp.pos_beamcoord = kaon.pos; + dp.pos = kaon.pos; + dp.pos.Transform(fBeam2Det); + dp.pos += Beam4; + + // Branch the parent Kaon Decay + double dp_mass = fM; + // std::pair decay = Branch(dp_mass, fMagUe4, fMagUm4, GetRandom()); + //double br = decay.first; + + double br = Pi0ToDPBR(fM); + + //bool is_muon = decay.second; + //double lep_mass = is_muon ? Constants::Instance().muon_mass : Constants::Instance().elec_mass; + if (br == 0.) return false; + if (fVerbose) std::cout << "BR: " << br << std::endl; + + // get the momentum direction in the kaon parent rest frame + double p = (mpi0 * mpi0 - fM * fM) / (2.0 * mpi0); + double e = sqrt(p*p + dp_mass * dp_mass); + // Two-body decays are isotropic + dp.mom = TLorentzVector(p*RandomUnitVector(), e); + + // boost to lab frame + TLorentzVector mom = dp.mom; + mom.Boost(kaon.mom.BoostVector()); + + dp.mom_beamcoord = mom; + // rotate to detector frame + dp.mom = mom; + dp.mom.Transform(fBeam2Det); + + dp.mmom_beamcoord = kaon.mom; + // also save the kaon momentum in the detector frame + dp.mmom = kaon.mom; + dp.mmom.Transform(fBeam2Det); + + // and save the secondary momentum + dp.sec = dp.mmom - dp.mom; + dp.sec_beamcoord = dp.mmom_beamcoord - dp.mom_beamcoord; + + // The weight is the importance weight times the branching-ratio weight + weight = kaon.weight * br / SMKaonBR(kaon.meson_pdg); + + // set the mixing + dp.C1 = fe; + dp.C2 = 0; + dp.C3 = 0.; + dp.mass = fM; + + dp.meson_pdg = kaon.meson_pdg; + dp.secondary_pdg = 22; + dp.generator = 2; // kDP + + // equivalent neutrino energy + dp.equiv_enu = EnuLab(flux.fnecm, dp.mmom, dp.pos); + + + /* // Get the DP Polarization + double meson_mass = Constants::Instance().kplus_mass; + if(abs(dp.meson_pdg) == 321) { + meson_mass = Constants::Instance().kplus_mass; + }else if(abs(dp.meson_pdg) == 211) { + meson_mass = Constants::Instance().piplus_mass; + } + */ + // dp.polarization = PolDP(fM , lep_mass, meson_mass); + //Account for the Polarization of m+ ->l+N being opposite to the polarization of m- -> l-bar{N} due to CP + // if(dp.secondary_pdg < 0) dp.polarization *= -1; + + return true; +} + +DEFINE_ART_CLASS_TOOL(PiZero2DPFlux) + +} // namespace ldm +} // namespace evgen diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/TxtFileGenNM_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/TxtFileGenNM_tool.cc new file mode 100644 index 000000000..48276be60 --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/Tools/TxtFileGenNM_tool.cc @@ -0,0 +1,360 @@ +/** + * + */ + +// Framework Includes +#include "art/Framework/Core/EDProducer.h" +#include "art/Framework/Principal/Event.h" +#include "art/Framework/Principal/Handle.h" +#include "art/Framework/Services/Registry/ServiceHandle.h" +#include "art/Persistency/Common/PtrMaker.h" +#include "art/Utilities/ToolMacros.h" +#include "cetlib/cpu_timer.h" +#include "fhiclcpp/ParameterSet.h" +#include "messagefacility/MessageLogger/MessageLogger.h" +#include "CLHEP/Random/RandFlat.h" +#include "ifdh_art/IFDHService/IFDH_service.h" + +#include "nusimdata/SimulationBase/MCFlux.h" + +// local includes +#include "IMesonGen.h" + +// std includes +#include +#include +#include + +//------------------------------------------------------------------------------------------------------------------------------------------ +// implementation follows + +namespace evgen { +namespace ldm { +/** + * @brief TxtFileGenNM class definiton + */ +class TxtFileGenNM : public IMesonGen +{ +public: + /** + * @brief Constructor + */ + TxtFileGenNM(fhicl::ParameterSet const &pset); + + /** + * @brief Destructor + */ + ~TxtFileGenNM(); + + double GetPOT() override; + simb::MCFlux GetNext() override; + + void configure(const fhicl::ParameterSet&) override; + + std::string GetNextEntry(); + std::vector LoadFluxFiles(); + simb::MCFlux MakeMCFlux(std::string line); + + // no weights + double MaxWeight() override { return -1.; } + +private: + // config + std::string fSearchPath; + std::vector fSearchPatterns; + unsigned long fMaxFluxFileMB; + std::string fFluxCopyMethod; + bool fRandomizeFiles; + int fNSkipLines; + bool fVerbose; + + // info for tracking files + unsigned fFileIndex; + bool fNewFile; + std::vector fFluxFiles; + std::ifstream fCurrentFile; + int fCurrentFileLines; + + // info for tracking entry in file + unsigned fEntry; + unsigned fEntryStart; + + // count POT + double fAccumulatedPOT; +}; + +TxtFileGenNM::TxtFileGenNM(fhicl::ParameterSet const &pset): + IMeVPrtlStage("TxtFileGenNM") +{ + configure(pset); + + // copy the flux files locally + fFluxFiles = LoadFluxFiles(); + + // setup indices + fFileIndex = 0; + fEntry = 0; + fEntryStart = 0; + fNewFile = true; + fCurrentFileLines = 0; + + fAccumulatedPOT = 0.; + +} + +//------------------------------------------------------------------------------------------------------------------------------------------ +TxtFileGenNM::~TxtFileGenNM() {} + +//------------------------------------------------------------------------------------------------------------------------------------------ +void TxtFileGenNM::configure(fhicl::ParameterSet const &pset) +{ + fSearchPath = pset.get("SearchPath"); + fSearchPatterns = pset.get>("FluxFiles"); + fMaxFluxFileMB = pset.get("MaxFluxFileMB", 2 * 1024); + fFluxCopyMethod = pset.get("FluxCopyMethod", "IFDH"); + fRandomizeFiles = pset.get("RandomizeFiles"); + fNSkipLines = pset.get("NSkipLines"); + fVerbose = pset.get("Verbose", false); + + std::cout << "Searching for flux files at path: " << fSearchPath << std::endl; + std::cout << "With patterns:\n"; + for (const std::string &s: fSearchPatterns) std::cout << s << std::endl; + std::cout << "With copy method: " << fFluxCopyMethod << std::endl; +} + +std::vector TxtFileGenNM::LoadFluxFiles() { + art::ServiceHandle ifdhp; + + std::vector> allFiles; + + // find the flux files + for (unsigned i = 0; i < fSearchPatterns.size(); i++) { + std::vector> thisList = ifdhp->findMatchingFiles(fSearchPath, fSearchPatterns[i]); + std::copy (thisList.begin(), thisList.end(), std::back_inserter(allFiles)); + } + + // first randomize the flux files + std::vector order(allFiles.size(), 0); + if (fRandomizeFiles) { + std::vector rand(allFiles.size(), 0.); + CLHEP::RandFlat::shootArray(fEngine, rand.size(), &rand[0]); + TMath::Sort(allFiles.size(), &rand[0], &order[0], false); + } + else { + for (unsigned i = 0; i < order.size(); i++) { + order[i] = i; + } + } + + // If we are directly accessing the files, no need to copy + if (fFluxCopyMethod == "DIRECT") { + std::cout << "DIRECTLY ACCESSING FLUX FILES.\n"; + std::vector files(allFiles.size()); + for (unsigned i = 0; i < order.size(); i++) { + files[i] = allFiles[order[i]].first; + } + return files; + } + + // copy over up to the provided limit + std::vector> selected; + unsigned long totalBytes = 0; + unsigned ind = 0; + while (totalBytes < (fMaxFluxFileMB * 1024 * 1024) && ind < allFiles.size()) { + selected.push_back(allFiles[order[ind]]); + totalBytes += allFiles[order[ind]].second; + ind ++; + } + + // copy the files locally + std::vector> localFiles = ifdhp->fetchSharedFiles(selected, fFluxCopyMethod); + + std::vector files(localFiles.size()); + for (unsigned i = 0; i < localFiles.size(); i++) { + files[i] = localFiles[i].first; + } + + return files; +} + +double TxtFileGenNM::GetPOT() { + double ret = fAccumulatedPOT; + fAccumulatedPOT = 0.; + return ret; +} + + + +std::string TxtFileGenNM::GetNextEntry() { + // new file -- set the start entry + if (fNewFile) { + // wrap file index around + if (fFileIndex >= fFluxFiles.size()) { + fFileIndex = 0; + } + + if (fVerbose) std::cout << "New file: " << fFluxFiles[fFileIndex] << " at index: " << fFileIndex << " of: " << fFluxFiles.size() << std::endl; + + if (fCurrentFile.is_open()) fCurrentFile.close(); + fCurrentFile.clear(); + fCurrentFile.open(fFluxFiles[fFileIndex]); + + if (!fCurrentFile.is_open()) { + throw cet::exception("TxtFileGenNM") + << "Could not open file " << fFluxFiles[fFileIndex]; + } + + // count the number of lines + std::string line; + int lines; + for(lines = 0; std::getline(fCurrentFile,line); lines++); + + fCurrentFileLines = lines - fNSkipLines; + if (fCurrentFileLines <= 0) { + throw cet::exception("TxtFileGenNM") + << "File " << fFluxFiles[fFileIndex] + << " has no usable data lines after skipping " + << fNSkipLines << " header lines. " + << "Total lines in file: " << lines; + } + // Seek back to start + fCurrentFile.clear(); + fCurrentFile.seekg(0); + + // Start at a random index in this file + fEntryStart = CLHEP::RandFlat::shootInt(fEngine, fCurrentFileLines); + fEntry = fEntryStart; + + // skip to that line in the file + for (lines = 0; lines < fNSkipLines + (int)fEntryStart && std::getline(fCurrentFile,line); lines++); + + fNewFile = false; + } + else { + fEntry = (fEntry + 1) % fCurrentFileLines; + + // if this is the last entry, get ready for the next file + if ((fEntry + 1) % fCurrentFileLines == fEntryStart) { + fFileIndex ++; + fNewFile = true; + } + } + + // Read the next line, if we are at the end of the file go back to the beginning + /* std::string thisline; + if (!std::getline(fCurrentFile, thisline)) { + + // seek back to start + fCurrentFile.clear(); + fCurrentFile.seekg(0); + + // skip to the first valid line + int lines; + std::string line; + for (lines = 0; lines < fNSkipLines && std::getline(fCurrentFile,line); lines++); + } + + return thisline;*/ + + std::string thisline; + if (!std::getline(fCurrentFile, thisline)) { + + fCurrentFile.clear(); + fCurrentFile.seekg(0); + + int lines; + std::string line; + for (lines = 0; lines < fNSkipLines && std::getline(fCurrentFile, line); ++lines) {} + + if (!std::getline(fCurrentFile, thisline)) { + throw cet::exception("TxtFileGenNM") + << "Failed to read a valid data line from file " + << fFluxFiles[fFileIndex] + << " after rewinding."; + } + } + return thisline; +} + + + +simb::MCFlux TxtFileGenNM::GetNext() { + std::string meson = GetNextEntry(); + return MakeMCFlux(meson); +} + +simb::MCFlux TxtFileGenNM::MakeMCFlux(std::string line) { + // std::cout << "Parsing line: " << line << std::endl; + + // read the 4-vector off the line + double px, py, pz,x, y, z, wgt, start_t; + // int pdgcode; + std::stringstream l4vec(line); + l4vec >> px >> py >> pz >> x >> y >> z >> start_t >> wgt; + + if (fVerbose) std::cout << "Values: " << px << py << pz << x << y << z << start_t << wgt << std::endl; + + simb::MCFlux flux; + + flux.fFluxType = simb::kSimple_Flux; // number for file gen.... + flux.fnimpwt = wgt; + flux.fvx = x; // At the target -- TODO is this ok??? + flux.fvy = y; + flux.fvz = z; + flux.fpdpx = px; + flux.fpdpy = py; + flux.fpdpz = pz; + flux.fppdxdz = px/pz; + flux.fppdydz = py/pz; + flux.fpppz = pz; + + double mpi0 = 0.1349768; + double p2 = px*px + py*py + pz*pz; + flux.fppenergy = std::sqrt(p2 + mpi0*mpi0); + + flux.fppmedium = -1; + flux.fptype = 111; + flux.fndecay = -1; + flux.fmuparpx = -1; + flux.fmuparpy = -1; + flux.fmuparpz = -1; + flux.fmupare = -1; + flux.fnecm = -1; + + flux.fppvx = 0.; + flux.fppvy = 0.; + flux.fppvz = 0.; + + flux.ftvx = -1; + flux.ftvy = -1; + flux.ftvz = -1; + flux.ftpx = start_t; + flux.ftpy = -1; + flux.ftpz = -1; + flux.ftptype = -1; + flux.ftgen = -1; + + flux.frun = -1; + flux.fevtno = -1; + flux.ftgptype = -1; + + // flux.fnenergyn = flux.fnenergyf = enu; + // flux.fnwtnear = flux.fnwtfar = wgt; + // ignore variables dealing with the neutrino + flux.fnenergyn = -1; + flux.fnwtnear = flux.fnwtfar = -1; + flux.fdk2gen = -1; + + // placeholder for time + flux.fxpoint = 0.; + + // Update the POT + fAccumulatedPOT = 1000000; + + return flux; +} + +DEFINE_ART_CLASS_TOOL(TxtFileGenNM) + +} // namespace ldm +} // namespace evgen diff --git a/sbncode/EventGenerator/MeVPrtl/config/DP/CMakeLists.txt b/sbncode/EventGenerator/MeVPrtl/config/DP/CMakeLists.txt new file mode 100644 index 000000000..13355789a --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/config/DP/CMakeLists.txt @@ -0,0 +1 @@ +install_fhicl() diff --git a/sbncode/EventGenerator/MeVPrtl/config/DP/dp.fcl b/sbncode/EventGenerator/MeVPrtl/config/DP/dp.fcl new file mode 100644 index 000000000..fb3f2cd1a --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/config/DP/dp.fcl @@ -0,0 +1,88 @@ +#include "bnb_dp_sbnd.fcl" + +BEGIN_PROLOG + +# ===== parameters you vary ===== +scalarM: 0.30 # GeV +CTau_cm: 100000 # c*tau in cm +BR_ee: 1.0 # BR(A -> e+e-) + +meson_energy: 8 + +epsilon: 1e-7 + +# ====================== +# FLUX: meson -> gamma + A +# ====================== +scalar_flux: { + tool_type: Meson2DP + + M: @local::scalarM + e: @local::epsilon + + # same semantics as old tool + Parents: [111] + CorrectDK2NU: true + SecondarySignConvention: "legacy" + + Beam2DetectorRotation: @local::sbnd_bnb_beam2detector_rotation + BeamOrigin: @local::sbnd_bnb_beam_origin + + SpillTimeConfig: "evgb::EvtTimeFNALBeam booster, dtbucket=18.936, sigma=1.308" + GlobalTimeOffset: 0 + + Verbose: false +} + +# ====================== +# RAYTRACE (same as before) +# ====================== +mxdraytrace: @local::mixedweight_ray_trace_box +mxdraytrace.ReferencePrtlMass: @local::scalarM +mxdraytrace.ReferenceScndPDG: 22 +mxdraytrace.ReferencePrimaryEnergy: @local::meson_energy +mxdraytrace.ReferencePrimPDG: 221 + +# ====================== +# DECAY: A -> ee +# ====================== +scalar_decay: { + tool_type: DPDecay + + AllowElectronDecay: true + AllowMuonDecay: true + AddTimeOfFlight: true + + # NEW required inputs +# CTau_cm: @local::CTau_cm + BR_ee: @local::BR_ee + + # optional MaxWeight precompute (same pattern as before, but uses CTau) + ReferenceRayLength: 7.549834e2 + ReferenceRayDistance: 110e2 + ReferenceMass: @local::scalarM + ReferenceCTau_cm: @local::CTau_cm + ReferenceEnergy: @local::meson_energy + + Epsilon: @local::epsilon + + Verbose: false +} + +# ====================== +# GENERATOR MODULE (same schema) +# ====================== +dp_generator: { + module_type: MeVPrtlGen + Deweight: false + Produce: true + AnaOutput: true + Verbose: false + + MesonGen: @local::bnb_pi0_v2 + Flux: @local::scalar_flux + RayTrace: @local::mxdraytrace + Decay: @local::scalar_decay +} + +END_PROLOG \ No newline at end of file diff --git a/sbncode/EventGenerator/MeVPrtl/config/DP/run_dp.fcl b/sbncode/EventGenerator/MeVPrtl/config/DP/run_dp.fcl new file mode 100644 index 000000000..93f606848 --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/config/DP/run_dp.fcl @@ -0,0 +1,46 @@ +#include "dp.fcl" +#include "simulationservices_sbnd.fcl" + +process_name: MeVPrtl + +services: { + @table::sbnd_simulation_services + + TFileService: { fileName: "hists_mevprtl.root" } + + IFDH: { } + + NuRandomService: { + service_type: "NuRandomService" + policy: "random" + } +} + +source: { module_type: EmptyEvent } + +physics: { + producers: { + generator: @local::dp_generator + } + + analyzers: { + + } + + simulate: [ generator ] + + stream: [ out ] + + trigger_paths: [ simulate ] + end_paths: [ stream ] +} + +outputs: { + out: { + module_type: RootOutput + fileName: "mevprtl_art.root" + dataTier: "simulated" + compressionLevel: 1 + saveMemoryObjectThreshold: 0 + } +} \ No newline at end of file diff --git a/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_common.fcl b/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_common.fcl new file mode 100644 index 000000000..bc0fb4bb8 --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_common.fcl @@ -0,0 +1,62 @@ +BEGIN_PROLOG + +empty_kaon: { + tool_type: EmptyKaonGen +} + + +bnb_pi0_txt: { + tool_type: "TxtFileGenNM" +# SearchPath: "/pnfs/sbnd/persistent/users/rohanr/beammc/neutral_meson_production_1e6pot_2025_07_07_g4v11.2_qbbc" + SearchPath: "/exp/sbnd/data/users/rohanr/BSM/MeVPrtl" + FluxFiles: ["output_pi0_small.txt"] + RandomizeFiles: true + NSkipLines: 0 + MaxFluxFileMB: 8192 # 8GB + FluxCopyMethod: DIRECT + Verbose: false +} + +bnb_pi0: { + + tool_type: "BNBPi0Gen" + SearchPath: "/pnfs/sbnd/persistent/users/rohanr/beammc/neutral_meson_production_1e6pot_2025_07_07_g4v11.2_qbbc/neutrals_primOnly_20250707/0/" + FluxFiles: ["*.dk2nu.root"] + TreeName: "dk2nuTree" + MetaTreeName: "dkmetaTree" + MaxFluxFileMB: 8192 # 8GB + FluxCopyMethod: DIRECT + RandomizeFiles: false + Verbose: false + +} + +bnb_pi0_v2: { + tool_type: "BNBKaonGenDK2NU" # BooNe or Dk2Nu Ntuples + FluxMode: "Dk2Nu" +# SearchPath: "/cvmfs/sbn.osgstorage.org/pnfs/fnal.gov/usr/sbn/persistent/stash/physics-rodrigoa/bnbflux/" # or "/pnfs/sbnd/persistent/G4BNB/" + SearchPath: "/pnfs/sbnd/persistent/users/rohanr/beammc/neutral_meson_production_1e6pot_2025_07_07_g4v11.2_qbbc/neutrals_primOnly_20250707/0/" + FluxFiles: ["*.dk2nu.root"] + TreeName: "dk2nuTree" + MetaTreeName: "dkmetaTree" + MaxFluxFileMB: 8192 # 8GB + FluxCopyMethod: DIRECT + RandomizeFiles: true + Verbose: false + +} + +bnb_pi0_boone: { + tool_type: "BNBKaonGen" # BooNe Ntuples + SearchPath: "/cvmfs/sbn.osgstorage.org/pnfs/fnal.gov/usr/sbn/persistent/stash/physics-rodrigoa/bnbflux/" + FluxFiles: ["*.root"] + TreeName: "h101" + MetaTreeName: "meta" + MaxFluxFileMB: 8192 # 8GB + FluxCopyMethod: DIRECT + RandomizeFiles: false + Verbose: false +} + + +END_PROLOG diff --git a/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl b/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl new file mode 100644 index 000000000..56d21839b --- /dev/null +++ b/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl @@ -0,0 +1,58 @@ +#include "bnb_pi0_common.fcl" + +BEGIN_PROLOG + +sbnd_bnb_beam2detector_rotation: [ 1, 0, 0, + 0, 1, 0, + 0, 0, 1] #bnb to sbnd is in z-direction, only need a translation. + +#sbnd_bnb_beam_origin: [-73.78, 0, -11000] # cm in beam in deterctor frame +sbnd_bnb_beam_origin: [0, 0, 0, 73.78, 0, 11000] # cm in detector in beam frame + +#sbnd detector in det frame +sbnd_detector_box: [-200, 200, -200, 200, 0, 500] #cm +sbnd_bnb_solid_angle_box: 1.3223e-3 #front face / detector distance ^2 = 4*4/110^2 + +sbnd_bnb_solid_angle_cryostat: 0.0133 + + +pi0_energy: 8 #GeV Max energy from pi0 +pi0_pdg: 111 #pi0 + +ray_trace_box: { + tool_type: RayTraceBox + Box: @local::sbnd_detector_box + Verbose: false +} + +rethrow_ray_trace_box: { + tool_type: ReThrowRayTraceBox + Box: @local::sbnd_detector_box + ReferenceLabSolidAngle: @local::sbnd_bnb_solid_angle_box + ReferencePrimaryEnergy: @local::pi0_energy + ReferencePrimPDG: @local::pi0_pdg + Verbose: false +} + +weighted_ray_trace_box: { + tool_type: WeightedRayTraceBox + Box: @local::sbnd_detector_box + ReferenceLabSolidAngle: @local::sbnd_bnb_solid_angle_box + ReferencePrimaryEnergy: @local::pi0_energy + ReferencePrimPDG: @local::pi0_pdg + Verbose: false +} + +mixedweight_ray_trace_box: { + tool_type: MixedWeightRayTraceBox + Box: @local::sbnd_detector_box + ReferenceLabSolidAngle: @local::sbnd_bnb_solid_angle_box + ReferencePrimaryEnergy: @local::pi0_energy + ReferencePrimPDG: @local::pi0_pdg + MaxWeightFudge: 2. + NThrow: 250 + FixNSuccess: false + Verbose: false +} + +END_PROLOG \ No newline at end of file From 12b6dcfcf767b99f2a5fb11d60a5b43d4ef878de Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Wed, 15 Apr 2026 10:11:00 -0500 Subject: [PATCH 02/14] Minor housekeeping changes for reading branching fraction tables --- .../MeVPrtl/Tools/DP/CMakeLists.txt | 62 +----- .../MeVPrtl/Tools/DP/DPDecay_tool.cc | 206 +++++++++++++++++- .../MeVPrtl/Tools/DP/old/CMakeLists.txt | 39 ---- .../EventGenerator/MeVPrtl/config/DP/dp.fcl | 25 ++- 4 files changed, 221 insertions(+), 111 deletions(-) diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/CMakeLists.txt b/sbncode/EventGenerator/MeVPrtl/Tools/DP/CMakeLists.txt index 05bf7c003..0f40c1184 100644 --- a/sbncode/EventGenerator/MeVPrtl/Tools/DP/CMakeLists.txt +++ b/sbncode/EventGenerator/MeVPrtl/Tools/DP/CMakeLists.txt @@ -1,26 +1,7 @@ -cet_build_plugin( PiZero2DPFlux art::tool - LIBRARIES - art::Framework_Core - art::Framework_Services_Registry - art_root_io::TFileService_service - art::Framework_Principal - art::Persistency_Common - art::Utilities canvas::canvas - cetlib::cetlib cetlib_except::cetlib_except - ROOT::EGPythia6 - CLHEP::CLHEP - sbnobj::Common_EventGen_MeVPrtl - nugen::EventGeneratorBase_GENIE - nusimdata::SimulationBase - nurandom::RandomUtils_NuRandomService_service - GSL::gsl - sbncode_EventGenerator_MeVPrtl_Constants - sbnobj::Common_EventGen_MeVPrtl -) - cet_build_plugin( DPDecay art::tool LIBRARIES + ifdh_art::IFDH_service art::Framework_Core art::Framework_Services_Registry art_root_io::TFileService_service @@ -37,6 +18,7 @@ cet_build_plugin( DPDecay art::tool GSL::gsl sbncode_EventGenerator_MeVPrtl_Constants sbnobj::Common_EventGen_MeVPrtl + ) cet_build_plugin( Meson2DP art::tool LIBRARIES @@ -59,47 +41,7 @@ cet_build_plugin( Meson2DP art::tool ) -cet_build_plugin( Eta2DPFlux art::tool - LIBRARIES - art::Framework_Core - art::Framework_Services_Registry - art_root_io::TFileService_service - art::Framework_Principal - art::Persistency_Common - art::Utilities canvas::canvas - cetlib::cetlib cetlib_except::cetlib_except - CLHEP::CLHEP - nurandom::RandomUtils_NuRandomService_service - nusimdata::SimulationBase - GSL::gsl - larcorealg::Geometry - sbncode_EventGenerator_MeVPrtl_Dalitz - sbncode_EventGenerator_MeVPrtl_AnThreeBD - sbncode_EventGenerator_MeVPrtl_Constants - sbnobj::Common_EventGen_MeVPrtl - nugen::EventGeneratorBase_GENIE -) -cet_build_plugin( DPMakeDecay art::tool - LIBRARIES - art::Framework_Core - art::Framework_Services_Registry - art_root_io::TFileService_service - art::Framework_Principal - art::Persistency_Common - art::Utilities canvas::canvas - cetlib::cetlib cetlib_except::cetlib_except - CLHEP::CLHEP - nurandom::RandomUtils_NuRandomService_service - nusimdata::SimulationBase - GSL::gsl - larcorealg::Geometry - sbncode_EventGenerator_MeVPrtl_Dalitz - sbncode_EventGenerator_MeVPrtl_AnThreeBD - sbncode_EventGenerator_MeVPrtl_AnTwoBD - sbncode_EventGenerator_MeVPrtl_Constants - sbnobj::Common_EventGen_MeVPrtl -) add_subdirectory(old) diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/DPDecay_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/DP/DPDecay_tool.cc index 6cef6f664..ce8a35fbc 100644 --- a/sbncode/EventGenerator/MeVPrtl/Tools/DP/DPDecay_tool.cc +++ b/sbncode/EventGenerator/MeVPrtl/Tools/DP/DPDecay_tool.cc @@ -1,3 +1,11 @@ +#include "cetlib/search_path.h" +#include "cetlib_except/exception.h" +#include "ifdh_art/IFDHService/IFDH_service.h" + +#include "art/Framework/Services/Registry/ServiceHandle.h" + +#include +#include #include "art/Utilities/ToolMacros.h" #include "fhiclcpp/ParameterSet.h" @@ -58,7 +66,17 @@ class DPDecay : public IMeVPrtlDecay { // double fCTau_cm = 1.0; // double fBR_ee = 1.0; double fEpsilon = -1.0; - std::vector fMassGrid; + + std::vector fRequestedTableFiles; + std::string fTableSearchPath; + std::string fTableCopyMethod; + bool fUseIFDHForTables = false; + std::vector fBRTables; + + std::vector fMassGridE; + std::vector fMassGridMu; + std::vector fMassGridHad; + std::vector fBRHad; std::vector fBRMu; std::vector fBRE; @@ -78,8 +96,13 @@ class DPDecay : public IMeVPrtlDecay { double Gamma_total(double m, double eps) const; + std::vector LoadTableFiles(); + void ReadTableFile(const std::string& fname, + std::vector& masses, + std::vector& vals) const; + }; - + /* auto load_table = [](const std::string& fname, std::vector& m, std::vector& br) { @@ -89,13 +112,33 @@ class DPDecay : public IMeVPrtlDecay { m.push_back(x); br.push_back(y); } - }; + };*/ DPDecay::DPDecay(fhicl::ParameterSet const& pset) : IMeVPrtlStage("DPDecay") { configure(pset); + fBRTables = LoadTableFiles(); + if (fBRTables.size() != 3) { + throw cet::exception("DPDecay") + << "Expected exactly 3 resolved table files, got " + << fBRTables.size() << ".\n"; + } + + ReadTableFile(fBRTables[0], fMassGridE, fBRE); + ReadTableFile(fBRTables[1], fMassGridMu, fBRMu); + ReadTableFile(fBRTables[2], fMassGridHad, fBRHad); + + if (fVerbose) { + mf::LogInfo("DPDecay") + << "Loaded table[0]: " << fBRTables[0] + << " with " << fBRE.size() << " rows\n" + << "Loaded table[1]: " << fBRTables[1] + << " with " << fBRMu.size() << " rows\n" + << "Loaded table[2]: " << fBRTables[2] + << " with " << fBRHad.size() << " rows"; + } } void DPDecay::configure(fhicl::ParameterSet const& pset) @@ -120,11 +163,34 @@ void DPDecay::configure(fhicl::ParameterSet const& pset) fReferenceCTau_cm = pset.get("ReferenceCTau_cm", -1.0); fReferenceEnergy = pset.get("ReferenceEnergy", -1.0); + fRequestedTableFiles = pset.get>("TableFiles"); + fTableSearchPath = pset.get("TableSearchPath", ""); + fTableCopyMethod = pset.get("TableCopyMethod", "DIRECT"); + fUseIFDHForTables = pset.get("UseIFDHForTables", false); + + if (fRequestedTableFiles.size() != 3) { + throw cet::exception("DPDecay") + << "FHiCL parameter TableFiles must contain exactly 3 entries " + << "(ee, mu_mu, hadrons). Got " + << fRequestedTableFiles.size() << ".\n"; + } + + if (fVerbose) { + mf::LogInfo("DPDecay") + << "Configured DPDecay with table files:\n" + << " [0] " << fRequestedTableFiles[0] << "\n" + << " [1] " << fRequestedTableFiles[1] << "\n" + << " [2] " << fRequestedTableFiles[2] << "\n" + << "UseIFDHForTables = " << fUseIFDHForTables << "\n" + << "TableCopyMethod = " << fTableCopyMethod << "\n" + << "TableSearchPath = " << fTableSearchPath; + } + /* load_table("bfrac_dark_photon_e_e.txt", fMassGrid, fBRE); load_table("bfrac_dark_photon_mu_mu.txt", fMassGrid, fBRMu); load_table("bfrac_dark_photon_hadrons.txt", fMassGrid, fBRHad); - + */ if (fReferenceRayLength > 0 && fReferenceMass > 0 && fReferenceCTau_cm > 0 && fReferenceEnergy > 0) { const double mS = fReferenceMass; @@ -140,6 +206,136 @@ void DPDecay::configure(fhicl::ParameterSet const& pset) fMaxWeight = -1.; } } + std::vector DPDecay::LoadTableFiles() + { + std::vector files; + files.reserve(fRequestedTableFiles.size()); + + // Case 1: use IFDH similarly to BNBKaonGen + if (fUseIFDHForTables) { + art::ServiceHandle ifdhp; + + std::vector> selected; + selected.reserve(fRequestedTableFiles.size()); + + for (const auto& pattern : fRequestedTableFiles) { + std::vector> found = + ifdhp->findMatchingFiles(fTableSearchPath, pattern); + + if (found.empty()) { + throw cet::exception("DPDecay") + << "LoadTableFiles: no match found for pattern '" + << pattern << "' in search path '" + << fTableSearchPath << "'.\n"; + } + + if (found.size() > 1) { + throw cet::exception("DPDecay") + << "LoadTableFiles: multiple matches found for pattern '" + << pattern << "' in search path '" + << fTableSearchPath << "'. " + << "Use a more specific filename/pattern.\n"; + } + + selected.push_back(found[0]); + } + + if (fTableCopyMethod == "DIRECT") { + for (const auto& f : selected) { + files.push_back(f.first); + } + return files; + } + + std::vector> localFiles = + ifdhp->fetchSharedFiles(selected, fTableCopyMethod); + + if (localFiles.size() != selected.size()) { + throw cet::exception("DPDecay") + << "LoadTableFiles: requested " << selected.size() + << " files, but fetched " << localFiles.size() << ".\n"; + } + + for (const auto& f : localFiles) { + files.push_back(f.first); + } + + return files; + } + + // Case 2: exact/local files or FW_SEARCH_PATH resolution + cet::search_path sp("FW_SEARCH_PATH"); + + for (const auto& requested : fRequestedTableFiles) { + std::string resolved = requested; + + // First try opening exactly as given + { + std::ifstream test(requested); + if (test.good()) { + files.push_back(requested); + continue; + } + } + + // Then try FW_SEARCH_PATH + if (!sp.find_file(requested, resolved)) { + char const* fw = std::getenv("FW_SEARCH_PATH"); + throw cet::exception("DPDecay") + << "LoadTableFiles: could not find table file '" + << requested + << "' either directly or via FW_SEARCH_PATH.\n" + << "FW_SEARCH_PATH is: " << (fw ? fw : "") << "\n"; + } + + files.push_back(resolved); + } + + return files; + } + + void DPDecay::ReadTableFile(const std::string& fname, + std::vector& masses, + std::vector& vals) const + { + masses.clear(); + vals.clear(); + + std::ifstream f(fname); + if (!f.is_open()) { + throw cet::exception("DPDecay") + << "ReadTableFile: failed to open file '" << fname << "'.\n"; + } + + double x, y; + while (f >> x >> y) { + masses.push_back(x); + vals.push_back(y); + } + + if (f.bad()) { + throw cet::exception("DPDecay") + << "ReadTableFile: I/O error while reading '" << fname << "'.\n"; + } + + if (masses.empty()) { + throw cet::exception("DPDecay") + << "ReadTableFile: file '" << fname << "' had no valid rows.\n"; + } + + if (masses.size() != vals.size()) { + throw cet::exception("DPDecay") + << "ReadTableFile: inconsistent table lengths in '" << fname << "'.\n"; + } + + for (size_t i = 1; i < masses.size(); ++i) { + if (masses[i] < masses[i-1]) { + throw cet::exception("DPDecay") + << "ReadTableFile: mass grid in '" << fname + << "' is not sorted ascending at row " << i << ".\n"; + } + } + } double DPDecay::interp(const std::vector& x, const std::vector& y, @@ -165,7 +361,7 @@ void DPDecay::configure(fhicl::ParameterSet const& pset) return Gamma_ll(m, eps, 0.000511) + Gamma_ll(m, eps, 0.105); } else { - double br_mu = interp(fMassGrid, fBRMu, m); + double br_mu = interp(fMassGridMu, fBRMu, m); double gmu = Gamma_ll(m, eps, 0.105); return (br_mu > 0) ? gmu / br_mu : 0.0; } diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/CMakeLists.txt b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/CMakeLists.txt index 04344c706..77830b4ad 100644 --- a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/CMakeLists.txt +++ b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/CMakeLists.txt @@ -19,45 +19,6 @@ cet_build_plugin( PiZero2DPFlux art::tool sbnobj::Common_EventGen_MeVPrtl ) -cet_build_plugin( ScalarDecayKevin art::tool - LIBRARIES - art::Framework_Core - art::Framework_Services_Registry - art_root_io::TFileService_service - art::Framework_Principal - art::Persistency_Common - art::Utilities canvas::canvas - cetlib::cetlib cetlib_except::cetlib_except - ROOT::EGPythia6 - CLHEP::CLHEP - sbnobj::Common_EventGen_MeVPrtl - nugen::EventGeneratorBase_GENIE - nusimdata::SimulationBase - nurandom::RandomUtils_NuRandomService_service - GSL::gsl - sbncode_EventGenerator_MeVPrtl_Constants - sbnobj::Common_EventGen_MeVPrtl -) -cet_build_plugin( Meson2ScalarKevin art::tool - LIBRARIES - art::Framework_Core - art::Framework_Services_Registry - art_root_io::TFileService_service - art::Framework_Principal - art::Persistency_Common - art::Utilities canvas::canvas - cetlib::cetlib cetlib_except::cetlib_except - ROOT::EGPythia6 - CLHEP::CLHEP - sbnobj::Common_EventGen_MeVPrtl - nugen::EventGeneratorBase_GENIE - nusimdata::SimulationBase - nurandom::RandomUtils_NuRandomService_service - GSL::gsl - sbncode_EventGenerator_MeVPrtl_Constants - sbnobj::Common_EventGen_MeVPrtl -) - cet_build_plugin( Eta2DPFlux art::tool LIBRARIES diff --git a/sbncode/EventGenerator/MeVPrtl/config/DP/dp.fcl b/sbncode/EventGenerator/MeVPrtl/config/DP/dp.fcl index fb3f2cd1a..9e77e6551 100644 --- a/sbncode/EventGenerator/MeVPrtl/config/DP/dp.fcl +++ b/sbncode/EventGenerator/MeVPrtl/config/DP/dp.fcl @@ -14,14 +14,14 @@ epsilon: 1e-7 # ====================== # FLUX: meson -> gamma + A # ====================== -scalar_flux: { +meson_flux: { tool_type: Meson2DP M: @local::scalarM e: @local::epsilon - # same semantics as old tool - Parents: [111] + + Parents: [221] CorrectDK2NU: true SecondarySignConvention: "legacy" @@ -31,7 +31,7 @@ scalar_flux: { SpillTimeConfig: "evgb::EvtTimeFNALBeam booster, dtbucket=18.936, sigma=1.308" GlobalTimeOffset: 0 - Verbose: false + Verbose: true } # ====================== @@ -66,7 +66,18 @@ scalar_decay: { Epsilon: @local::epsilon - Verbose: false + UseIFDHForTables: false + TableCopyMethod: "DIRECT" + TableSearchPath: "/pnfs/sbnd/persistent/users/rohanr/dp/br/" + TableFiles: [ + "/pnfs/sbnd/persistent/users/rohanr/dp/br/bfrac_dark_photon_e_e.txt", + "/pnfs/sbnd/persistent/users/rohanr/dp/br/bfrac_dark_photon_mu_mu.txt", + "/pnfs/sbnd/persistent/users/rohanr/dp/br/bfrac_dark_photon_hadrons.txt" + ] + + + + Verbose: true } # ====================== @@ -77,10 +88,10 @@ dp_generator: { Deweight: false Produce: true AnaOutput: true - Verbose: false + Verbose: true MesonGen: @local::bnb_pi0_v2 - Flux: @local::scalar_flux + Flux: @local::meson_flux RayTrace: @local::mxdraytrace Decay: @local::scalar_decay } From a1667bef5b7dd7ebdc870150cc468c7f9ffb72f5 Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Wed, 15 Apr 2026 10:19:17 -0500 Subject: [PATCH 03/14] Bug fix to Meson2DP --- sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc index e538cab44..539e5abb7 100644 --- a/sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc +++ b/sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc @@ -149,10 +149,10 @@ bool Meson2DP::MakeFlux(const simb::MCFlux& flux, const int gamma_pdg = 22; - const double mPi0 = pdg_mass_GeV(221); + const double mMeson = pdg_mass_GeV(221); const double mgamma = 0.0; - const double pstar = twobody_momentum(mPi0, mgamma, mA); + const double pstar = twobody_momentum(mMeson, mgamma, mA); if (pstar < 0) return false; const double eA = std::sqrt(pstar*pstar + mA*mA); From f1dc00720914fb92ac2c0fca1270470ccb65d0c9 Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Wed, 15 Apr 2026 10:25:26 -0500 Subject: [PATCH 04/14] Update to weighttracing --- .../MeVPrtl/config/bnb_dp_sbnd.fcl | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl b/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl index 56d21839b..8b4ae8b83 100644 --- a/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl +++ b/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl @@ -16,8 +16,8 @@ sbnd_bnb_solid_angle_box: 1.3223e-3 #front face / detector distance ^2 = 4*4/110 sbnd_bnb_solid_angle_cryostat: 0.0133 -pi0_energy: 8 #GeV Max energy from pi0 -pi0_pdg: 111 #pi0 +meson_energy: 8 #GeV Max energy from meson +meson_pdg: 221 #eta ray_trace_box: { tool_type: RayTraceBox @@ -29,8 +29,8 @@ rethrow_ray_trace_box: { tool_type: ReThrowRayTraceBox Box: @local::sbnd_detector_box ReferenceLabSolidAngle: @local::sbnd_bnb_solid_angle_box - ReferencePrimaryEnergy: @local::pi0_energy - ReferencePrimPDG: @local::pi0_pdg + ReferencePrimaryEnergy: @local::meson_energy + ReferencePrimPDG: @local::meson_pdg Verbose: false } @@ -38,8 +38,8 @@ weighted_ray_trace_box: { tool_type: WeightedRayTraceBox Box: @local::sbnd_detector_box ReferenceLabSolidAngle: @local::sbnd_bnb_solid_angle_box - ReferencePrimaryEnergy: @local::pi0_energy - ReferencePrimPDG: @local::pi0_pdg + ReferencePrimaryEnergy: @local::meson_energy + ReferencePrimPDG: @local::meson_pdg Verbose: false } @@ -47,8 +47,8 @@ mixedweight_ray_trace_box: { tool_type: MixedWeightRayTraceBox Box: @local::sbnd_detector_box ReferenceLabSolidAngle: @local::sbnd_bnb_solid_angle_box - ReferencePrimaryEnergy: @local::pi0_energy - ReferencePrimPDG: @local::pi0_pdg + ReferencePrimaryEnergy: @local::meson_energy + ReferencePrimPDG: @local::meson_pdg MaxWeightFudge: 2. NThrow: 250 FixNSuccess: false From eaff8b6140ba3776a407fbfb1662aebdebee033d Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Fri, 17 Apr 2026 04:22:54 -0500 Subject: [PATCH 05/14] First iteration of changes to SBNEventWeight and FluxReader --- .../job/run_fluxreader_dk2nu_sbnd.fcl | 7 + .../FluxReader/job/run_fluxreader_sbnd.fcl | 51 +++++- .../run_fluxreader_sbnd_SBNEventWeight.fcl | 1 + .../Calculators/BNBFlux/FluxCalcPrep.cxx | 129 +++++++++++++++- .../BNBFlux/FluxHistWeightCalc.cxx | 146 ++++++++++++++++++ .../jobs/flux/eventweight_flux_sbn.fcl | 25 ++- 6 files changed, 349 insertions(+), 10 deletions(-) create mode 100644 sbncode/FluxReader/job/run_fluxreader_dk2nu_sbnd.fcl create mode 100644 sbncode/SBNEventWeight/Calculators/BNBFlux/FluxHistWeightCalc.cxx diff --git a/sbncode/FluxReader/job/run_fluxreader_dk2nu_sbnd.fcl b/sbncode/FluxReader/job/run_fluxreader_dk2nu_sbnd.fcl new file mode 100644 index 000000000..51c91068a --- /dev/null +++ b/sbncode/FluxReader/job/run_fluxreader_dk2nu_sbnd.fcl @@ -0,0 +1,7 @@ +# Driver fcl file for reading in BooNE files +# for SBND +#include "genie_sbnd.fcl" +#include "run_fluxreader_sbnd.fcl" + +source.inputType: "dk2nu" + diff --git a/sbncode/FluxReader/job/run_fluxreader_sbnd.fcl b/sbncode/FluxReader/job/run_fluxreader_sbnd.fcl index 646ff8953..7aff74197 100644 --- a/sbncode/FluxReader/job/run_fluxreader_sbnd.fcl +++ b/sbncode/FluxReader/job/run_fluxreader_sbnd.fcl @@ -23,11 +23,58 @@ source: module_type: FluxReader skipEvents: 0 maxEvents: -1 - inputType: "gsimple" + inputType: "dk2nu" + dk2nuConfig: "dk2nu_sbnd_v3" nBins: 200 Elow: 0 Ehigh: 10 SelfIncrementRun: true + dk2nu_sbnd: { + rotmatrix: [ 1, 0, 0, + 0, 1, 0, + 0, 0, 1] + userbeam: [ 73.78, 0, 11000] + + #x_detAV: [-200, 200] + #y_detAV: [-200, 200] + #z_detAV: [0, 500] + + windowBase: [ 500, 500, -1000 ] + window1: [ 500, -500, -1000 ] + window2: [ -500, 500, -1000 ] + + } + dk2nu_sbnd_v2: { + rotmatrix: [ 1, 0, 0, + 0, 1, 0, + 0, 0, 1] + userbeam: [ 0, 0, 0, 73.78, 0, 11000] + + + windowBase: [ 500, 500, -1000 ] + window1: [ 0, -1000, 0 ] + window2: [ -1000, 0, 0 ] + + } +dk2nu_sbnd_v3: { + userbeam: [ -73.78, 0, 11000 ] + rotmatrix: [ 1, 0, 0, + 0, 1, 0, + 0, 0, 1 ] + windowBase: [ 500, 500, -1000 ] + window1: [ -500, 500, -1000 ] + window2: [ 500, -500, -1000 ] + } + dk2nu_bnb_at_uboone_v1: { + userbeam: [ -130., 0., 47000 ] + #userbeam: [ -73.78, 0., -11000.] + rotmatrix: [ 1, 0, 0, + 0, 1, 0, + 0, 0, 1 ] + windowBase: [ 630, 500, -1000 ] + window1: [ 630, -500, -1000 ] + window2: [ -370, 500, -1000 ] + } } outputs: @@ -38,7 +85,7 @@ outputs: fileName: "fluxreader.root" compressionLevel: 1 dataTier: "simulated" - SelectEvents: [ filter ] + SelectEvents: [ filter ] } } diff --git a/sbncode/FluxReader/job/run_fluxreader_sbnd_SBNEventWeight.fcl b/sbncode/FluxReader/job/run_fluxreader_sbnd_SBNEventWeight.fcl index 37949eb6f..89269228d 100644 --- a/sbncode/FluxReader/job/run_fluxreader_sbnd_SBNEventWeight.fcl +++ b/sbncode/FluxReader/job/run_fluxreader_sbnd_SBNEventWeight.fcl @@ -38,6 +38,7 @@ physics.producers.fluxweight.weight_functions_flux: [horncurrent , kzero , piplus , piminus + , fluxhist ] # Need to overwrite the parameter weight_functions as weight_functions_flux; diff --git a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.cxx b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.cxx index d832e8638..806f01de5 100644 --- a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.cxx +++ b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.cxx @@ -44,6 +44,9 @@ namespace sbn { CalcType = pset.get< std::string >("calc_type");//Unisim,PrimaryHadronSWCentralSplineVariation,PrimaryHadronFeynmanScaling,PrimaryHadronSanfordWang,PrimaryHadronNormalization std::cout<<"SBNEventWeight Flux: Calculator type: "<("use_flux_hist", false); + fScalePos = pset.get("scale_factor_pos"); if(!pset.get_if_present("scale_factor_neg",fScaleNeg)){ std::cout<<"SBNEventWeight Flux: auto-assignment: scale_factor_neg = 1."<("cv_hist_file")); + std::string rw_file = sp.find_file(pset.get("rw_hist_file")); + */ + std::string cv_file = "/exp/sbnd/app/users/rohanr/larsoft_v10_14_02/srcs/sbncode/sbncode/SBNEventWeight/jobs/flux/nuMom_immParent_merged.root"; + std::string rw_file = "/exp/sbnd/app/users/rohanr/larsoft_v10_14_02/srcs/sbncode/sbncode/SBNEventWeight/jobs/flux/nuMom_immParent_oldFiles_correctedName.root"; + TFile fcv(cv_file.c_str()); + TFile frw(rw_file.c_str()); + + std::string nutype[4] = {"numu", "numubar", "nue", "nuebar"}; + // int pdglist[7] = {211, -211, 321, -321, 130, 13, -13}; + + std::vector> validCombinations = { + {211, "numu"}, + {-211, "numubar"}, + {321, "numu"}, + {-321, "numubar"}, + {130, "nue"}, + {13, "numu"}, + {-13, "numubar"} + }; + /* + for (int ip=0; ip<7; ip++) { + for (int in=0; in<4; in++) { + + std::string hname = Form("hSBND_%d_%s_pz", pdglist[ip], nutype[in].c_str()); + + TH1F* hcv = (TH1F*)fcv.Get(hname.c_str()); + TH1F* hrw = (TH1F*)frw.Get(hname.c_str()); + + if (!hcv || !hrw) { + throw cet::exception("FluxHist") + << "Missing histogram: " << hname; + } + + for (int ib=0; ib<200; ib++) { + fCVHist[ip][in][ib] = hcv->GetBinContent(ib+1); + fRWHist[ip][in][ib] = hrw->GetBinContent(ib+1); + } + } + } + */ + + for (size_t i = 0; i < validCombinations.size(); ++i) { + int pdg = std::get<0>(validCombinations[i]); + std::string nut = std::get<1>(validCombinations[i]); + + std::string hname = Form("hSBND_%d_%s_pz", pdg, nut.c_str()); + + TH1F* hcv = (TH1F*)fcv.Get(hname.c_str()); + TH1F* hrw = (TH1F*)frw.Get(hname.c_str()); + + if (!hcv || !hrw) { + throw cet::exception("FluxHist") + << "Missing histogram: " << hname; + } + + for (int ib = 0; ib < 200; ++ib) { + fCVHist[i][ib] = hcv->GetBinContent(ib + 1); + fRWHist[i][ib] = hrw->GetBinContent(ib + 1); + } + } + fcv.Close(); + frw.Close(); + } + + //------------- //-- Hadrons -- //------------- - } else if( CalcType.compare(0, 13,"PrimaryHadron") == 0){//Hadron Calculators + else if( CalcType.compare(0, 13,"PrimaryHadron") == 0){//Hadron Calculators fprimaryHad = pset.get< std::vector>("PrimaryHadronGeantCode"); @@ -224,7 +299,7 @@ namespace sbn { } //or do the above 3 lines in one line -// auto const& mclist = *e.getValidHandle>(fGeneratorModuleLabel); + auto const& mclist = *e.getValidHandle>(fGeneratorModuleLabel); // If no neutrinos in this event, gives 0 weight; int NUni = fParameterSet.fNuniverses; @@ -290,7 +365,53 @@ namespace sbn { } }//Iterate through the number of universes } - } else{//then this must be PrimaryHadron + } + + else if (CalcType == "FluxHist") { + + weights.resize(NUni); + + int p7 = GetPType7(fluxlist[inu].fptype); + + + if (fluxlist[inu].fntype == 14) ntype7 = 0; + else if (fluxlist[inu].fntype == -14) ntype7 = 1; + else if (fluxlist[inu].fntype == 12) ntype7 = 2; + else if (fluxlist[inu].fntype == -12) ntype7 = 3; + else { + throw cet::exception(__FUNCTION__) + << "Unknown neutrino type " << fluxlist[inu].fntype; + } + + double enu = fluxlist[inu].fnenergyn; + if (enu <= 0) + enu = mclist[inu].GetNeutrino().Nu().E(); + + int bin = std::min(199, int(enu / 0.05)); + + if(fParameterSet.fRWType == EventWeightParameterSet::kMultiSim){ + + for (int i = 0; i < NUni; i++) { + + double randomN = (fParameterSet.fParameterMap.begin())->second[i]; + + // double cv = fCVHist[p7][ntype7][bin]; + // double rw = fRWHist[p7][ntype7][bin]; + + double cv = fCVHist[p7][bin]; + double rw = fRWHist[p7][bin]; + + double w = 1.0; + + if (cv > 0 && std::isfinite(rw/cv)) { + w = 1 - (1 - rw/cv) * randomN; + } + + weights[i] = std::isfinite(w) ? w : 1.0; + } + } + } + else{//then this must be PrimaryHadron // First let's check that the parent of the neutrino we are looking for is diff --git a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxHistWeightCalc.cxx b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxHistWeightCalc.cxx new file mode 100644 index 000000000..230fbd8c9 --- /dev/null +++ b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxHistWeightCalc.cxx @@ -0,0 +1,146 @@ +#include "larsim/EventWeight/Base/WeightCalcCreator.h" +#include "larsim/EventWeight/Base/WeightCalc.h" + +#include + +#include "art/Framework/Core/ModuleMacros.h" +#include "art/Framework/Core/EDProducer.h" +#include "nurandom/RandomUtils/NuRandomService.h" + +#include "CLHEP/Random/RandGaussQ.h" + +#include "nusimdata/SimulationBase/MCFlux.h" +#include "nusimdata/SimulationBase/MCTruth.h" + +#include "TFile.h" +#include "TH1F.h" + +namespace evwgh { + class FluxHistWeightCalc : public WeightCalc + { + public: + FluxHistWeightCalc() = default; + void Configure(fhicl::ParameterSet const& pset, + CLHEP::HepRandomEngine& engine); + std::vector > GetWeight(art::Event & e); + + private: + std::vector fWeightArray{}; + int fNmultisims{}; + std::string fMode{}; + std::string fGenieModuleLabel{}; + + // pi+-,k+-,k0,mu+- + // | numu, numubar, nue, nuebar + // | | 50MeV bins + // | | | + double fCV[7][4][200]; + double fRW[7][4][200]; + + DECLARE_WEIGHTCALC(FluxHistWeightCalc) + }; + + void FluxHistWeightCalc::Configure(fhicl::ParameterSet const& p, + CLHEP::HepRandomEngine& engine) + { + //global config + fGenieModuleLabel= p.get< std::string > ("genie_module_label"); + + fhicl::ParameterSet const &pset=p.get (GetName()); + //calc config + fNmultisims = pset.get("number_of_multisims"); + fMode = pset.get("mode"); + std::string dataInput1 = pset.get< std::string >("cv_hist_file"); + std::string dataInput2 = pset.get< std::string >("rw_hist_file"); + + cet::search_path sp("FW_SEARCH_PATH"); + std::string cvfile = sp.find_file(dataInput1); + std::string rwfile = sp.find_file(dataInput2); + + std::string ptype[] = {"pi+", "pi-", "k+", "k-", "k0", "mu-", "mu+"}; + std::string ntype[] = {"numu", "numubar", "nue", "nuebar"}; + + TFile fcv(Form("%s",cvfile.c_str())); + TFile frw(Form("%s",rwfile.c_str())); + for (int iptyp=0;iptyp<7;iptyp++) { + for (int intyp=0;intyp<4;intyp++) { + for (int ibin=0;ibin<200;ibin++) { + fCV[iptyp][intyp][ibin]=(dynamic_cast (fcv.Get(Form("h_%s_%s",ptype[iptyp].c_str(),ntype[intyp].c_str()))))->GetBinContent(ibin+1); + fRW[iptyp][intyp][ibin]=(dynamic_cast (frw.Get(Form("h_%s_%s",ptype[iptyp].c_str(),ntype[intyp].c_str()))))->GetBinContent(ibin+1); + } + } + } + fcv.Close(); + frw.Close(); + + fWeightArray.resize(fNmultisims); + + if (fMode.find("multisim") != std::string::npos ) + for (double& weight : fWeightArray) weight = CLHEP::RandGaussQ::shoot(&engine, 0, 1.); + else + for (double& weight : fWeightArray) weight = 1.; + } + + std::vector > FluxHistWeightCalc::GetWeight(art::Event & e) + { + //calculate weight(s) here + std::vector > weight; + + // * MC flux information + auto mcfluxListHandle = e.getHandle< std::vector >(fGenieModuleLabel); + if (!mcfluxListHandle) { + return weight; + } + + // * MC truth information + auto mctruthListHandle = e.getHandle< std::vector >(fGenieModuleLabel); + if (!mctruthListHandle) { + return weight; + } + + std::vector const& fluxlist = *mcfluxListHandle; + std::vector const& mclist = *mctruthListHandle; + + weight.resize(mclist.size()); + for (unsigned int inu=0;inu Date: Sun, 19 Apr 2026 11:33:01 -0500 Subject: [PATCH 06/14] New stable release for Weighting, fixes tree production for FluxHist --- sbncode/FluxReader/CMakeLists.txt | 1 + sbncode/FluxReader/FluxReaderAna_module.cc | 115 +++++++++ .../FluxReader/job/run_fluxreader_sbnd.fcl | 12 +- ...n_fluxreader_sbnd_boone_SBNEventWeight.fcl | 50 ++++ ...n_fluxreader_sbnd_dk2nu_SBNEventWeight.fcl | 49 ++++ .../Calculators/BNBFlux/CMakeLists.txt | 1 + .../Calculators/BNBFlux/FluxCalcPrep.cxx | 223 +++++++++++------- .../Calculators/BNBFlux/FluxCalcPrep.h | 20 +- .../BNBFlux/FluxHistWeightCalc.cxx | 105 ++++++++- .../jobs/run_eventweight_sbn.fcl | 1 + 10 files changed, 482 insertions(+), 95 deletions(-) create mode 100644 sbncode/FluxReader/job/run_fluxreader_sbnd_boone_SBNEventWeight.fcl create mode 100644 sbncode/FluxReader/job/run_fluxreader_sbnd_dk2nu_SBNEventWeight.fcl diff --git a/sbncode/FluxReader/CMakeLists.txt b/sbncode/FluxReader/CMakeLists.txt index ad70d3c22..8e1eb9098 100644 --- a/sbncode/FluxReader/CMakeLists.txt +++ b/sbncode/FluxReader/CMakeLists.txt @@ -74,6 +74,7 @@ cet_make_library( cet_build_plugin(FluxReaderAna art::module LIBRARIES sbncode_FluxReader sbncode_FluxReader_FluxInterface + sbnobj::Common_SBNEventWeight nusimdata::SimulationBase larcoreobj::SummaryData larcore::Geometry_Geometry_service diff --git a/sbncode/FluxReader/FluxReaderAna_module.cc b/sbncode/FluxReader/FluxReaderAna_module.cc index 914c71da7..11080a1a3 100644 --- a/sbncode/FluxReader/FluxReaderAna_module.cc +++ b/sbncode/FluxReader/FluxReaderAna_module.cc @@ -35,6 +35,20 @@ #include "nusimdata/SimulationBase/MCFlux.h" #include "nusimdata/SimulationBase/MCTruth.h" + +#include "canvas/Persistency/Common/FindManyP.h" +#include "canvas/Persistency/Common/Ptr.h" +#include "canvas/Persistency/Common/PtrVector.h" +#include "sbnobj/Common/SBNEventWeight/EventWeightMap.h" + + +#include +#include +#include +#include +#include +#include + class FluxReaderAna; @@ -101,6 +115,19 @@ class FluxReaderAna : public art::EDAnalyzer { float _nu_other_y; /// Y poisition of neutrino at the front face of the TPC (other) float _nu_other_z; /// Z poisition of neutrino at the front face of the TPC (other) float _nu_other_t; /// Time of the neutrino (other) + + + //For weighting: + std::string _flux_eventweight_multisim_producer; + bool _save_systs_flux; + + int _evtwgt_flux_nfunc; /// Number of flux weight functions + std::vector _evtwgt_flux_funcname; /// Names of weight functions + std::vector _evtwgt_flux_nweight; /// Number of weights per function + std::vector> _evtwgt_flux_weight; /// Raw weights by function + std::vector _evtwgt_flux_oneweight; /// Combined flux multisim weight + + }; @@ -122,6 +149,10 @@ FluxReaderAna::FluxReaderAna(fhicl::ParameterSet const& p) _x_cut = p.get("XCut"); // cm _y_cut = p.get("YCut"); // cm + _flux_eventweight_multisim_producer = + p.get("FluxEventWeightProducer", "fluxweight"); + + _save_systs_flux = p.get("SaveSystsFlux", false); art::ServiceHandle fs; _tree = fs->make("tree", ""); @@ -154,6 +185,14 @@ FluxReaderAna::FluxReaderAna(fhicl::ParameterSet const& p) _tree->Branch("nu_other_y", &_nu_other_y, "nu_other_y/F"); _tree->Branch("nu_other_z", &_nu_other_z, "nu_other_z/F"); _tree->Branch("nu_other_t", &_nu_other_t, "nu_other_t/F"); + + + _tree->Branch("evtwgt_flux_nfunc", &_evtwgt_flux_nfunc, "evtwgt_flux_nfunc/I"); + _tree->Branch("evtwgt_flux_funcname", "std::vector", &_evtwgt_flux_funcname); + _tree->Branch("evtwgt_flux_nweight", "std::vector", &_evtwgt_flux_nweight); + _tree->Branch("evtwgt_flux_weight", "std::vector>", &_evtwgt_flux_weight); + _tree->Branch("evtwgt_flux_oneweight", "std::vector", &_evtwgt_flux_oneweight); + } void FluxReaderAna::analyze(art::Event const& e) @@ -167,6 +206,12 @@ void FluxReaderAna::analyze(art::Event const& e) e.getByLabel(_flux_label, mctruthHandle); std::vector const& mclist = *mctruthHandle; + std::vector> mct_v; + art::fill_ptr_vector(mct_v, mctruthHandle); + + art::FindManyP mct_to_fluxewm(mctruthHandle, e, + _flux_eventweight_multisim_producer); + for(unsigned int inu = 0; inu < mclist.size(); inu++) { simb::MCParticle nu = mclist[inu].GetNeutrino().Nu(); simb::MCFlux flux = fluxlist[inu]; @@ -228,6 +273,76 @@ void FluxReaderAna::analyze(art::Event const& e) } } + // Reset flux systematic containers every neutrino + _evtwgt_flux_nfunc = 0; + _evtwgt_flux_funcname.clear(); + _evtwgt_flux_nweight.clear(); + _evtwgt_flux_weight.clear(); + _evtwgt_flux_oneweight.clear(); + + if (_save_systs_flux) { + + std::vector> flux_ewm_v = mct_to_fluxewm.at(inu); + + if (flux_ewm_v.size() == 1) { + + std::map> evtwgt_map = *(flux_ewm_v[0]); + + std::vector previous_weights; + std::vector final_weights; + + int countFunc = 0; + + for (auto const& it : evtwgt_map) { + std::string const& func_name = it.first; + std::vector const& weight_v = it.second; + + if (previous_weights.empty()) { + previous_weights.resize(weight_v.size(), 1.f); + final_weights.resize(weight_v.size(), 1.f); + } + + // Protect against mismatched universe counts + if (weight_v.size() != previous_weights.size()) { + mf::LogWarning("FluxReaderAna") + << "Weight function " << func_name + << " has size " << weight_v.size() + << " but previous combined weight size is " + << previous_weights.size() + << ". Skipping this function."; + continue; + } + + _evtwgt_flux_funcname.push_back(func_name); + _evtwgt_flux_weight.push_back(weight_v); + _evtwgt_flux_nweight.push_back((int)weight_v.size()); + countFunc++; + + std::transform(previous_weights.begin(), previous_weights.end(), + weight_v.begin(), + final_weights.begin(), + std::multiplies()); + + previous_weights = final_weights; + } + + _evtwgt_flux_nfunc = countFunc; + _evtwgt_flux_oneweight = final_weights; + } + else if (flux_ewm_v.empty()) { + mf::LogWarning("FluxReaderAna") + << "No associated EventWeightMap found for neutrino index " + << inu << " from producer " << _flux_eventweight_multisim_producer; + } + else { + mf::LogWarning("FluxReaderAna") + << "Found " << flux_ewm_v.size() + << " associated EventWeightMaps for neutrino index " << inu + << " from producer " << _flux_eventweight_multisim_producer + << ", expected 1."; + } + } + _tree->Fill(); } } diff --git a/sbncode/FluxReader/job/run_fluxreader_sbnd.fcl b/sbncode/FluxReader/job/run_fluxreader_sbnd.fcl index 7aff74197..45a272c1b 100644 --- a/sbncode/FluxReader/job/run_fluxreader_sbnd.fcl +++ b/sbncode/FluxReader/job/run_fluxreader_sbnd.fcl @@ -55,8 +55,18 @@ source: window1: [ 0, -1000, 0 ] window2: [ -1000, 0, 0 ] - } + } dk2nu_sbnd_v3: { + userbeam: [ 73.78, 0, 11000 ] + rotmatrix: [ 1, 0, 0, + 0, 1, 0, + 0, 0, 1 ] + windowBase: [ 500, 500, -1000 ] + window1: [ -500, 500, -1000 ] + window2: [ 500, -500, -1000 ] + } + +dk2nu_sbnd_leo: { userbeam: [ -73.78, 0, 11000 ] rotmatrix: [ 1, 0, 0, 0, 1, 0, diff --git a/sbncode/FluxReader/job/run_fluxreader_sbnd_boone_SBNEventWeight.fcl b/sbncode/FluxReader/job/run_fluxreader_sbnd_boone_SBNEventWeight.fcl new file mode 100644 index 000000000..f7f447bbe --- /dev/null +++ b/sbncode/FluxReader/job/run_fluxreader_sbnd_boone_SBNEventWeight.fcl @@ -0,0 +1,50 @@ +# Driver fcl file for reading in gsimple files +# for SBND +# Add SBNEventWeight -- Keng Lin June 2021 + +#include "seedservice.fcl" +#include "services_sbnd.fcl" +#include "eventweight_flux_sbn.fcl" +#include "eventweight_genie_sbn.fcl" + +#include "run_fluxreader_sbnd.fcl" + + +source.inputType: "boone" + +physics.producers.fluxweight: @local::sbn_eventweight_flux +# physics.producers.genieweight: @local::sbn_eventweight_genie + +physics.filter: [ rns + , fluxfilter + , fluxweight + # , genieweight + ] + + +# physics.filters.fluxfilter.volumes: ["volWorld"] + +physics.producers.fluxweight.generator_module_label: flux + +# Customize what kind of weights we need, i.e. define weight_functions_flux: +physics.producers.fluxweight.weight_functions_flux: [horncurrent + , expskin + , pioninexsec + , pionqexsec + , piontotxsec + , nucleoninexsec + , nucleonqexsec + , nucleontotxsec + , kplus + , kminus + , kzero + , piplus + , piminus + , fluxhist + ] + +# Need to overwrite the parameter weight_functions as weight_functions_flux; +physics.producers.fluxweight.weight_functions: @local::physics.producers.fluxweight.weight_functions_flux + + + diff --git a/sbncode/FluxReader/job/run_fluxreader_sbnd_dk2nu_SBNEventWeight.fcl b/sbncode/FluxReader/job/run_fluxreader_sbnd_dk2nu_SBNEventWeight.fcl new file mode 100644 index 000000000..521629c6f --- /dev/null +++ b/sbncode/FluxReader/job/run_fluxreader_sbnd_dk2nu_SBNEventWeight.fcl @@ -0,0 +1,49 @@ +# Driver fcl file for reading in gsimple files +# for SBND +# Add SBNEventWeight -- Keng Lin June 2021 + +#include "seedservice.fcl" +#include "services_sbnd.fcl" +#include "eventweight_flux_sbn.fcl" +#include "eventweight_genie_sbn.fcl" + +#include "run_fluxreader_sbnd.fcl" + +source.inputType: "dk2nu" + +physics.producers.fluxweight: @local::sbn_eventweight_flux +# physics.producers.genieweight: @local::sbn_eventweight_genie + +physics.filter: [ rns + , fluxfilter + , fluxweight + # , genieweight + ] + + +# physics.filters.fluxfilter.volumes: ["volWorld"] + +physics.producers.fluxweight.generator_module_label: flux + +# Customize what kind of weights we need, i.e. define weight_functions_flux: +physics.producers.fluxweight.weight_functions_flux: [horncurrent + , expskin + , pioninexsec + , pionqexsec + , piontotxsec + , nucleoninexsec + , nucleonqexsec + , nucleontotxsec + , kplus + , kminus + , kzero + , piplus + , piminus + , fluxhist + ] + +# Need to overwrite the parameter weight_functions as weight_functions_flux; +physics.producers.fluxweight.weight_functions: @local::physics.producers.fluxweight.weight_functions_flux + + + diff --git a/sbncode/SBNEventWeight/Calculators/BNBFlux/CMakeLists.txt b/sbncode/SBNEventWeight/Calculators/BNBFlux/CMakeLists.txt index 37733ab95..ff8e10d4d 100644 --- a/sbncode/SBNEventWeight/Calculators/BNBFlux/CMakeLists.txt +++ b/sbncode/SBNEventWeight/Calculators/BNBFlux/CMakeLists.txt @@ -13,6 +13,7 @@ art_make_library( fhiclcpp::fhiclcpp cetlib::cetlib nusimdata::SimulationBase + larsim::EventWeight_Base ROOT::Hist ) diff --git a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.cxx b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.cxx index 806f01de5..c10a7b6d3 100644 --- a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.cxx +++ b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.cxx @@ -97,73 +97,77 @@ namespace sbn { } // G4BNB to BooNE + + else if (CalcType == "FluxHist") { - /* std::string cv_file = sp.find_file(pset.get("cv_hist_file")); - std::string rw_file = sp.find_file(pset.get("rw_hist_file")); - */ - std::string cv_file = "/exp/sbnd/app/users/rohanr/larsoft_v10_14_02/srcs/sbncode/sbncode/SBNEventWeight/jobs/flux/nuMom_immParent_merged.root"; - std::string rw_file = "/exp/sbnd/app/users/rohanr/larsoft_v10_14_02/srcs/sbncode/sbncode/SBNEventWeight/jobs/flux/nuMom_immParent_oldFiles_correctedName.root"; - TFile fcv(cv_file.c_str()); - TFile frw(rw_file.c_str()); - - std::string nutype[4] = {"numu", "numubar", "nue", "nuebar"}; - // int pdglist[7] = {211, -211, 321, -321, 130, 13, -13}; + // For debugging you can keep hardcoded paths for now. + // Later you can switch back to FHiCL-controlled file names. + std::string cv_file = + "/exp/sbnd/app/users/rohanr/larsoft_v10_14_02/srcs/sbncode/sbncode/SBNEventWeight/jobs/flux/nuMom_immParent_merged.root"; + std::string rw_file = + "/exp/sbnd/app/users/rohanr/larsoft_v10_14_02/srcs/sbncode/sbncode/SBNEventWeight/jobs/flux/nuMom_immParent_oldFiles_correctedName.root"; + + TFile fcv(cv_file.c_str()); + TFile frw(rw_file.c_str()); + + if (fcv.IsZombie() || frw.IsZombie()) { + throw cet::exception("FluxHist") + << "Could not open FluxHist ROOT file(s):\n" + << " CV = " << cv_file << "\n" + << " RW = " << rw_file << "\n"; + } std::vector> validCombinations = { - {211, "numu"}, - {-211, "numubar"}, - {321, "numu"}, - {-321, "numubar"}, - {130, "nue"}, - {13, "numu"}, - {-13, "numubar"} + { 211, "numu" }, + { 211, "nue" }, + {-211, "numubar" }, + {-211, "nuebar" }, + { 321, "numu" }, + { 321, "nue" }, + {-321, "numubar" }, + {-321, "nuebar" }, + { 130, "nue" }, + { 130, "nuebar" }, + { 13, "numu" }, + { 13, "nuebar" }, + { -13, "numubar" }, + { -13, "nue" } }; - /* - for (int ip=0; ip<7; ip++) { - for (int in=0; in<4; in++) { - - std::string hname = Form("hSBND_%d_%s_pz", pdglist[ip], nutype[in].c_str()); - - TH1F* hcv = (TH1F*)fcv.Get(hname.c_str()); - TH1F* hrw = (TH1F*)frw.Get(hname.c_str()); - - if (!hcv || !hrw) { - throw cet::exception("FluxHist") - << "Missing histogram: " << hname; - } - - for (int ib=0; ib<200; ib++) { - fCVHist[ip][in][ib] = hcv->GetBinContent(ib+1); - fRWHist[ip][in][ib] = hrw->GetBinContent(ib+1); - } - } - } - */ - - for (size_t i = 0; i < validCombinations.size(); ++i) { - int pdg = std::get<0>(validCombinations[i]); + for (size_t i = 0; i < validCombinations.size(); ++i) { + int pdg = std::get<0>(validCombinations[i]); std::string nut = std::get<1>(validCombinations[i]); std::string hname = Form("hSBND_%d_%s_pz", pdg, nut.c_str()); - TH1F* hcv = (TH1F*)fcv.Get(hname.c_str()); - TH1F* hrw = (TH1F*)frw.Get(hname.c_str()); - - if (!hcv || !hrw) { - throw cet::exception("FluxHist") - << "Missing histogram: " << hname; - } - - for (int ib = 0; ib < 200; ++ib) { - fCVHist[i][ib] = hcv->GetBinContent(ib + 1); - fRWHist[i][ib] = hrw->GetBinContent(ib + 1); - } - } - fcv.Close(); - frw.Close(); - } + TH1* hcv = dynamic_cast(fcv.Get(hname.c_str())); + TH1* hrw = dynamic_cast(frw.Get(hname.c_str())); + + if (!hcv || !hrw) { + throw cet::exception("FluxHist") + << "Missing histogram: " << hname << "\n"; + } + + /* std::cout << "Loaded histogram: " << hname + << " CV entries=" << hcv->GetEntries() + << " RW entries=" << hrw->GetEntries() + << std::endl; + */ + if (hcv->GetNbinsX() < 200 || hrw->GetNbinsX() < 200) { + throw cet::exception("FluxHist") + << "Histogram " << hname + << " has fewer than 200 bins.\n"; + } + for (int ib = 0; ib < 200; ++ib) { + fCVHist[i][ib] = hcv->GetBinContent(ib + 1); + fRWHist[i][ib] = hrw->GetBinContent(ib + 1); + } + } + + fcv.Close(); + frw.Close(); + } //------------- @@ -369,48 +373,91 @@ namespace sbn { else if (CalcType == "FluxHist") { - weights.resize(NUni); + std::cout << "Entering FluxHist GetWeight for inu = " << inu << std::endl; - int p7 = GetPType7(fluxlist[inu].fptype); + weights.resize(NUni, 1.0); - - if (fluxlist[inu].fntype == 14) ntype7 = 0; - else if (fluxlist[inu].fntype == -14) ntype7 = 1; - else if (fluxlist[inu].fntype == 12) ntype7 = 2; - else if (fluxlist[inu].fntype == -12) ntype7 = 3; - else { - throw cet::exception(__FUNCTION__) - << "Unknown neutrino type " << fluxlist[inu].fntype; - } + if (inu >= fluxlist.size()) { + throw cet::exception("FluxHist") + << "inu out of range for fluxlist: inu=" << inu + << " fluxlist.size()=" << fluxlist.size() << "\n"; + } - double enu = fluxlist[inu].fnenergyn; - if (enu <= 0) - enu = mclist[inu].GetNeutrino().Nu().E(); + if (inu >= mclist.size()) { + throw cet::exception("FluxHist") + << "inu out of range for mclist: inu=" << inu + << " mclist.size()=" << mclist.size() << "\n"; + } - int bin = std::min(199, int(enu / 0.05)); + int parent_pdg = fluxlist[inu].fptype; + int nu_pdg = fluxlist[inu].fntype; - if(fParameterSet.fRWType == EventWeightParameterSet::kMultiSim){ + /* std::cout << " parent PDG = " << parent_pdg + << ", neutrino PDG = " << nu_pdg << std::endl; + */ + int idx = GetFluxHistIndex(parent_pdg, nu_pdg); - for (int i = 0; i < NUni; i++) { + //std::cout << " FluxHist index = " << idx << std::endl; - double randomN = (fParameterSet.fParameterMap.begin())->second[i]; + if (idx < 0 || idx >= 14) { + std::cout << " Unsupported parent/flavor combination, returning unit weights" + << std::endl; + return weights; + } - // double cv = fCVHist[p7][ntype7][bin]; - // double rw = fRWHist[p7][ntype7][bin]; - - double cv = fCVHist[p7][bin]; - double rw = fRWHist[p7][bin]; - - double w = 1.0; + double pz = mclist[inu].GetNeutrino().Nu().Pz(); - if (cv > 0 && std::isfinite(rw/cv)) { - w = 1 - (1 - rw/cv) * randomN; - } + std::cout << " neutrino pz = " << pz << std::endl; - weights[i] = std::isfinite(w) ? w : 1.0; - } - } + int bin = static_cast(pz / 0.05); + + if (bin < 0) bin = 0; + if (bin > 199) bin = 199; + + std::cout << " histogram bin = " << bin << std::endl; + + if (fParameterSet.fRWType == EventWeightParameterSet::kMultiSim) { + + auto const& randomVec = (fParameterSet.fParameterMap.begin())->second; + + std::cout << " NUni = " << NUni + << ", randomVec.size() = " << randomVec.size() << std::endl; + + for (int i = 0; i < NUni; ++i) { + + if (i >= (int)randomVec.size()) { + throw cet::exception("FluxHist") + << "Random vector too short: i=" << i + << " size=" << randomVec.size() << "\n"; + } + + // double randomN = randomVec[i]; + + double cv = fCVHist[idx][bin]; + double rw = fRWHist[idx][bin]; + + /* std::cout << " universe " << i + << ": cv=" << cv + << " rw=" << rw + << " randomN=" << randomN << std::endl; + */ + double w = 1.0; + + if (cv > 0.0) { + double ratio = rw / cv; + if (std::isfinite(ratio)) { + w = ratio;//1.0 - (1.0 - ratio) * randomN; + } + } + + weights[i] = std::isfinite(w) ? w : 1.0; + } + } + + std::cout << "Leaving FluxHist GetWeight" << std::endl; } + + else{//then this must be PrimaryHadron diff --git a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.h b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.h index 57f1d568b..e5fbe4548 100644 --- a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.h +++ b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.h @@ -15,7 +15,7 @@ #include "sbncode/SBNEventWeight/Base/SmearingUtils.h"//MultiGaussianSmearing! //#include //for exit(0); debugging purpose - +#include "TH1.h" #include "TH1F.h" #include "TFile.h" #include "TDecompChol.h"//for Choleskey Decomposition @@ -69,6 +69,24 @@ namespace sbn { double fRWneg[4][4][200]; bool PosOnly{false}; + //for FluxHist + bool fUseFluxHist = false; + // double fCVHist[7][4][200]; + // double fRWHist[7][4][200]; + + double fCVHist[14][200]{}; + double fRWHist[14][200]{}; + + int GetFluxHistIndex(int parent_pdg, int nu_pdg) const { + if (parent_pdg == 211 && nu_pdg == 14) return 0; + else if (parent_pdg == -211 && nu_pdg == -14) return 1; + else if (parent_pdg == 321 && nu_pdg == 14) return 2; + else if (parent_pdg == -321 && nu_pdg == -14) return 3; + else if (parent_pdg == 130 && nu_pdg == 12) return 4; + else if (parent_pdg == 13 && nu_pdg == 14) return 5; + else if (parent_pdg == -13 && nu_pdg == -14) return 6; + else return -1; + } //for HadronsProduction std::vector fprimaryHad = {0}; //-- FeynmanScaling diff --git a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxHistWeightCalc.cxx b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxHistWeightCalc.cxx index 230fbd8c9..f783b7ad8 100644 --- a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxHistWeightCalc.cxx +++ b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxHistWeightCalc.cxx @@ -14,6 +14,10 @@ #include "TFile.h" #include "TH1F.h" +#include "TH1.h" + +#include +#include namespace evwgh { class FluxHistWeightCalc : public WeightCalc @@ -30,13 +34,29 @@ namespace evwgh { std::string fMode{}; std::string fGenieModuleLabel{}; + int GetFluxHistIndex(int parent_pdg, int nu_pdg) const { + if (parent_pdg == 211 && nu_pdg == 14) return 0; // pi+ -> numu + else if (parent_pdg == -211 && nu_pdg == -14) return 1; // pi- -> numubar + else if (parent_pdg == 321 && nu_pdg == 14) return 2; // k+ -> numu + else if (parent_pdg == -321 && nu_pdg == -14) return 3; // k- -> numubar + else if (parent_pdg == 130 && nu_pdg == 12) return 4; // k0 -> nue + else if (parent_pdg == 13 && nu_pdg == 14) return 5; // mu- -> numu + else if (parent_pdg == -13 && nu_pdg == -14) return 6; // mu+ -> numubar + else return -1; + } + + // pi+-,k+-,k0,mu+- // | numu, numubar, nue, nuebar // | | 50MeV bins // | | | - double fCV[7][4][200]; - double fRW[7][4][200]; + // double fCV[7][4][200]; + // double fRW[7][4][200]; + double fCV[14][200]{}; + double fRW[14][200]{}; + + DECLARE_WEIGHTCALC(FluxHistWeightCalc) }; @@ -60,16 +80,59 @@ namespace evwgh { std::string ptype[] = {"pi+", "pi-", "k+", "k-", "k0", "mu-", "mu+"}; std::string ntype[] = {"numu", "numubar", "nue", "nuebar"}; + std::vector> validCombinations = { + { 211, "numu" }, + { 211, "nue" }, + {-211, "numubar" }, + {-211, "nuebar" }, + { 321, "numu" }, + { 321, "nue" }, + {-321, "numubar" }, + {-321, "nuebar" }, + { 130, "nue" }, + { 130, "nuebar" }, + { 13, "numu" }, + { 13, "nuebar" }, + { -13, "numubar" }, + { -13, "nue" } + }; + TFile fcv(Form("%s",cvfile.c_str())); TFile frw(Form("%s",rwfile.c_str())); - for (int iptyp=0;iptyp<7;iptyp++) { + /* for (int iptyp=0;iptyp<7;iptyp++) { for (int intyp=0;intyp<4;intyp++) { for (int ibin=0;ibin<200;ibin++) { fCV[iptyp][intyp][ibin]=(dynamic_cast (fcv.Get(Form("h_%s_%s",ptype[iptyp].c_str(),ntype[intyp].c_str()))))->GetBinContent(ibin+1); fRW[iptyp][intyp][ibin]=(dynamic_cast (frw.Get(Form("h_%s_%s",ptype[iptyp].c_str(),ntype[intyp].c_str()))))->GetBinContent(ibin+1); } } + }*/ + + for (size_t i = 0; i < validCombinations.size(); ++i) { + int pdg = std::get<0>(validCombinations[i]); + std::string nut = std::get<1>(validCombinations[i]); + + std::string hname = Form("hSBND_%d_%s_pz", pdg, nut.c_str()); + + TH1* hcv = dynamic_cast(fcv.Get(hname.c_str())); + TH1* hrw = dynamic_cast(frw.Get(hname.c_str())); + + if (!hcv || !hrw) { + throw cet::exception("FluxHistWeightCalc") + << "Missing histogram: " << hname << "\n"; + } + + if (hcv->GetNbinsX() < 200 || hrw->GetNbinsX() < 200) { + throw cet::exception("FluxHistWeightCalc") + << "Histogram " << hname << " has fewer than 200 bins.\n"; + } + + for (int ibin = 0; ibin < 200; ++ibin) { + fCV[i][ibin] = hcv->GetBinContent(ibin + 1); + fRW[i][ibin] = hrw->GetBinContent(ibin + 1); + } } + fcv.Close(); frw.Close(); @@ -104,7 +167,39 @@ namespace evwgh { weight.resize(mclist.size()); for (unsigned int inu=0;inu(pz / 0.05); + if (bin < 0) bin = 0; + if (bin > 199) bin = 199; + + for (int i = 0; i < fNmultisims; ++i) { + double cv = fCV[idx][bin]; + double rw = fRW[idx][bin]; + + double test = 1.0; + + if (cv > 0.0) { + double ratio = rw / cv; + if (std::isfinite(ratio)) { + test = 1.0 - (1.0 - ratio) * fWeightArray[i]; + } + } + + weight[inu][i] = std::isfinite(test) ? test : 1.0; + } + + /* int ptype=-9999; int ntype=-9999; int bin=-9999; @@ -137,7 +232,7 @@ namespace evwgh { if(std::isfinite(test)){ weight[inu][i] = test;} else{weight[inu][i] = 1;} - } + }*/ } return weight; } diff --git a/sbncode/SBNEventWeight/jobs/run_eventweight_sbn.fcl b/sbncode/SBNEventWeight/jobs/run_eventweight_sbn.fcl index 64085ea1c..148585c15 100644 --- a/sbncode/SBNEventWeight/jobs/run_eventweight_sbn.fcl +++ b/sbncode/SBNEventWeight/jobs/run_eventweight_sbn.fcl @@ -35,3 +35,4 @@ outputs: { # Need to overwrite the parameter `weight_functions` to get recongnized physics.producers.genieweight.weight_functions: @local::physics.producers.genieweight.weight_functions_genie physics.producers.fluxweight.weight_functions: @local::physics.producers.fluxweight.weight_functions_flux + From 2d11ee8adce61ac48eb71f98fbe87fcf8bf72742 Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Wed, 29 Apr 2026 08:10:50 -0500 Subject: [PATCH 07/14] Updates to include 3D histogram functionality --- .../Calculators/BNBFlux/FluxCalcPrep.cxx | 486 +++++++++++++----- .../Calculators/BNBFlux/FluxCalcPrep.h | 195 ++++--- .../jobs/flux/eventweight_flux_sbn.fcl | 4 +- 3 files changed, 482 insertions(+), 203 deletions(-) diff --git a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.cxx b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.cxx index c10a7b6d3..713e98d20 100644 --- a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.cxx +++ b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.cxx @@ -9,7 +9,7 @@ namespace sbn { //Configure everything here! void FluxWeightCalc::Configure(fhicl::ParameterSet const& p, - CLHEP::HepRandomEngine& engine) { + CLHEP::HepRandomEngine& engine) { std::cout<<"SBNEventWeight Flux: configure "<< GetName() << std::endl; fGeneratorModuleLabel = p.get("generator_module_label");//use this label to get MC*Handle @@ -22,12 +22,12 @@ namespace sbn { std::vector< float > parsigmas(pars.size(), 1.0); if (pars.size() != parsigmas.size()) { throw cet::exception(__PRETTY_FUNCTION__) << GetName() << ": " - << "parameter_list and parameter_sigma length mismatch." - << std::endl; + << "parameter_list and parameter_sigma length mismatch." + << std::endl; } if(!pset.get_if_present("parameter_sigma", parsigmas)){ - std::cout<<"SBNEventWeight Flux: `parameter_sigma` was not set; now it is set as 1"<("mode");//3 types: multisim/pmNsigma/fixed @@ -49,8 +49,8 @@ namespace sbn { fScalePos = pset.get("scale_factor_pos"); if(!pset.get_if_present("scale_factor_neg",fScaleNeg)){ - std::cout<<"SBNEventWeight Flux: auto-assignment: scale_factor_neg = 1."<("CentralValue_hist_file"); - std::string cvfile_path = sp.find_file(dataInput1); + std::string dataInput1 = pset.get< std::string >("CentralValue_hist_file"); + std::string cvfile_path = sp.find_file(dataInput1); TFile fcv(Form("%s",cvfile_path.c_str())); - std::string dataInput2pos = pset.get< std::string >("PositiveSystematicVariation_hist_file"); - std::string rwfilepos = sp.find_file(dataInput2pos); + std::string dataInput2pos = pset.get< std::string >("PositiveSystematicVariation_hist_file"); + std::string rwfilepos = sp.find_file(dataInput2pos); TFile frwpos(Form("%s", rwfilepos.c_str())); - std::string dataInput2neg = pset.get< std::string >("NegativeSystematicVariation_hist_file"); - std::string rwfileneg = sp.find_file(dataInput2neg); + std::string dataInput2neg = pset.get< std::string >("NegativeSystematicVariation_hist_file"); + std::string rwfileneg = sp.find_file(dataInput2neg); TFile frwneg(Form("%s", rwfileneg.c_str())); if(dataInput2pos == dataInput2neg) PosOnly = true;//true - for skin depth @@ -100,13 +100,23 @@ namespace sbn { else if (CalcType == "FluxHist") { - + // For debugging you can keep hardcoded paths for now. // Later you can switch back to FHiCL-controlled file names. - std::string cv_file = - "/exp/sbnd/app/users/rohanr/larsoft_v10_14_02/srcs/sbncode/sbncode/SBNEventWeight/jobs/flux/nuMom_immParent_merged.root"; - std::string rw_file = - "/exp/sbnd/app/users/rohanr/larsoft_v10_14_02/srcs/sbncode/sbncode/SBNEventWeight/jobs/flux/nuMom_immParent_oldFiles_correctedName.root"; + // std::string cv_file = + //"/exp/sbnd/app/users/rohanr/larsoft_v10_14_02/srcs/sbncode/sbncode/SBNEventWeight/jobs/flux/nuMom_immParent_merged.root"; + // "/pnfs/sbnd/scratch/users/rohanr/beamweight/final_hists/nuMom_immParent_merged_200.root"; + // std::string rw_file = + //"/exp/sbnd/app/users/rohanr/larsoft_v10_14_02/srcs/sbncode/sbncode/SBNEventWeight/jobs/flux/nuMom_immParent_oldFiles_correctedName.root"; + // "/pnfs/sbnd/scratch/users/rohanr/beamweight/final_hists/nuMom_immParent_oldFiles_200_merged.root"; + + std::string dataInputCV = pset.get("cv_hist_file"); + std::string dataInputRW = pset.get("rw_hist_file"); + + cet::search_path sp("FW_SEARCH_PATH"); + + std::string cv_file = sp.find_file(dataInputCV); + std::string rw_file = sp.find_file(dataInputRW); TFile fcv(cv_file.c_str()); TFile frw(rw_file.c_str()); @@ -127,6 +137,8 @@ namespace sbn { { 321, "nue" }, {-321, "numubar" }, {-321, "nuebar" }, + { 130, "numu" }, + { 130, "numubar" }, { 130, "nue" }, { 130, "nuebar" }, { 13, "numu" }, @@ -134,37 +146,88 @@ namespace sbn { { -13, "numubar" }, { -13, "nue" } }; + + for (size_t i = 0; i < validCombinations.size(); ++i) { + int pdg = std::get<0>(validCombinations[i]); + std::string nut = std::get<1>(validCombinations[i]); + + std::string hname = Form("hSBND_%d_%s_3mom", pdg, nut.c_str()); + + TH3D* hcv = dynamic_cast(fcv.Get(hname.c_str())); + TH3D* hrw = dynamic_cast(frw.Get(hname.c_str())); + + if (!hcv || !hrw) { + throw cet::exception("FluxHist") + << "Missing TH3D histogram: " << hname << "\n"; + } + + fCVHist3D[i] = dynamic_cast(hcv->Clone(Form("%s_cv_clone", hname.c_str()))); + fRWHist3D[i] = dynamic_cast(hrw->Clone(Form("%s_rw_clone", hname.c_str()))); + + if (!fCVHist3D[i] || !fRWHist3D[i]) { + throw cet::exception("FluxHist") + << "Failed to clone TH3D histogram: " << hname << "\n"; + } + + fCVHist3D[i]->SetDirectory(nullptr); + fRWHist3D[i]->SetDirectory(nullptr); + + std::cout << "Loaded 3D histogram: " << hname + << " CV entries=" << fCVHist3D[i]->GetEntries() + << " RW entries=" << fRWHist3D[i]->GetEntries() + << std::endl; + } + + /* + std::string compNames[3] = {"px", "py", "pz"}; + for (size_t i = 0; i < validCombinations.size(); ++i) { int pdg = std::get<0>(validCombinations[i]); std::string nut = std::get<1>(validCombinations[i]); - std::string hname = Form("hSBND_%d_%s_pz", pdg, nut.c_str()); + for (int icomp = 0; icomp < 3; ++icomp) { + std::string hname = Form("hSBND_%d_%s_%s", pdg, nut.c_str(), compNames[icomp].c_str()); + + TH1* hcv = dynamic_cast(fcv.Get(hname.c_str())); + TH1* hrw = dynamic_cast(frw.Get(hname.c_str())); + + if (!hcv || !hrw) { + throw cet::exception("FluxHist") + << "Missing histogram: " << hname << "\n"; + } + + // std::cout << "Loaded histogram: " << hname + << " CV entries=" << hcv->GetEntries() + << " RW entries=" << hrw->GetEntries() + << std::endl; + // + if (hcv->GetNbinsX() < 200 || hrw->GetNbinsX() < 200) { + throw cet::exception("FluxHist") + << "Histogram " << hname + << " has fewer than 200 bins.\n"; + } - TH1* hcv = dynamic_cast(fcv.Get(hname.c_str())); - TH1* hrw = dynamic_cast(frw.Get(hname.c_str())); + fCVHist[i][icomp] = + dynamic_cast(hcv->Clone(Form("%s_cv_clone", hname.c_str()))); + fRWHist[i][icomp] = + dynamic_cast(hrw->Clone(Form("%s_rw_clone", hname.c_str()))); - if (!hcv || !hrw) { - throw cet::exception("FluxHist") - << "Missing histogram: " << hname << "\n"; - } + if (!fCVHist[i][icomp] || !fRWHist[i][icomp]) { + throw cet::exception("FluxHist") + << "Failed to clone histogram: " << hname << "\n"; + } - /* std::cout << "Loaded histogram: " << hname - << " CV entries=" << hcv->GetEntries() - << " RW entries=" << hrw->GetEntries() - << std::endl; - */ - if (hcv->GetNbinsX() < 200 || hrw->GetNbinsX() < 200) { - throw cet::exception("FluxHist") - << "Histogram " << hname - << " has fewer than 200 bins.\n"; - } + fCVHist[i][icomp]->SetDirectory(nullptr); + fRWHist[i][icomp]->SetDirectory(nullptr); - for (int ib = 0; ib < 200; ++ib) { - fCVHist[i][ib] = hcv->GetBinContent(ib + 1); - fRWHist[i][ib] = hrw->GetBinContent(ib + 1); - } - } + std::cout << "Loaded histogram: " << hname + << " CV entries=" << fCVHist[i][icomp]->GetEntries() + << " RW entries=" << fRWHist[i][icomp]->GetEntries() + << std::endl; + } + } +*/ fcv.Close(); frw.Close(); } @@ -183,11 +246,11 @@ namespace sbn { } else{//Other Hadron Calculators - std::string dataInput = pset.get< std::string >("ExternalData"); - std::string ExternalDataInput = sp.find_file(dataInput); + std::string dataInput = pset.get< std::string >("ExternalData"); + std::string ExternalDataInput = sp.find_file(dataInput); TFile* file = new TFile(Form("%s",ExternalDataInput.c_str())); - std::vector< std::string > pname; // these are keys to histograms + std::vector< std::string > pname; // these are keys to histograms if( CalcType == "PrimaryHadronFeynmanScaling" ){//k+ pname.push_back("FS/KPlus/FSKPlusFitVal"); @@ -209,9 +272,9 @@ namespace sbn { }else if( CalcType == "PrimaryHadronSWCentralSplineVariation" ){//pi+- - std::string fitInput = pset.get< std::string >("ExternalFit"); - std::string HadronName; - std::string HadronAbriviation; + std::string fitInput = pset.get< std::string >("ExternalFit"); + std::string HadronName; + std::string HadronAbriviation; if(fprimaryHad[0] == 211){ HadronName = "PiPlus"; HadronAbriviation = "PP"; @@ -254,10 +317,10 @@ namespace sbn { // //////////////// - std::string ExternalFitInput = sp.find_file(fitInput); + std::string ExternalFitInput = sp.find_file(fitInput); TFile* Fitfile = new TFile(Form("%s",ExternalFitInput.c_str())); - std::string fitname; // these are what we will extract from the file + std::string fitname; // these are what we will extract from the file fitname = Form("SW/%s/SW%sFitVal",HadronName.c_str(),HadronName.c_str()); // Sanford-Wang Fit Parameters TArrayD* SWParamArray = (TArrayD*) Fitfile->Get(fitname.c_str()); @@ -275,21 +338,21 @@ namespace sbn { }else { throw cet::exception(__PRETTY_FUNCTION__) << GetName() << ": " - <<" calculator "+CalcType + "is invalid" - < FluxWeightCalc::GetWeight(art::Event& e, size_t inu) { bool count_weights = false; -// std::cout<<"SBNEventWeight : getweight for the "< > mcFluxHandle; e.getByLabel(fGeneratorModuleLabel, mcFluxHandle); @@ -309,12 +372,12 @@ namespace sbn { int NUni = fParameterSet.fNuniverses; std::vector weights;//( mclist.size(), 0); if(fluxlist.size() == 0){ - std::cout<<"SBNEventWeight Flux: EMPTY WEIGHTS"<second[i]; weights[i]=UnisimWeightCalc(enu, ptype, ntype, randomN , PosOnly);//AddParameter result does not work here; - if(count_weights){ - if(weights[i]<0){ - wcn++; - }else if((weights[i]-0)<1e-30){ - wc0++; - }else if(fabs(weights[i]-30) < 1e-30){ - wc30++; - } else if(fabs(weights[i]-1)<1e-30){ - wc1++; - } else { - wc++; + if(count_weights){ + if(weights[i]<0){ + wcn++; + }else if((weights[i]-0)<1e-30){ + wc0++; + }else if(fabs(weights[i]-30) < 1e-30){ + wc30++; + } else if(fabs(weights[i]-1)<1e-30){ + wc1++; + } else { + wc++; + } + } + }//Iterate through the number of universes } } - }//Iterate through the number of universes + + else if (CalcType == "FluxHist") { + + weights.resize(NUni, 1.0); + + if (inu >= fluxlist.size()) { + throw cet::exception("FluxHist") + << "inu out of range for fluxlist: inu=" << inu + << " fluxlist.size()=" << fluxlist.size() << "\n"; + } + + if (inu >= mclist.size()) { + throw cet::exception("FluxHist") + << "inu out of range for mclist: inu=" << inu + << " mclist.size()=" << mclist.size() << "\n"; + } + + int parent_pdg = fluxlist[inu].fptype; + int nu_pdg = fluxlist[inu].fntype; + + double px = mclist[inu].GetNeutrino().Nu().Px(); + double py = mclist[inu].GetNeutrino().Nu().Py(); + double pz = mclist[inu].GetNeutrino().Nu().Pz(); + + double w = FluxHistWeightCalc(parent_pdg, nu_pdg, px, py, pz); + + for (int i = 0; i < NUni; ++i) { + weights[i] = std::isfinite(w) ? w : 1.0; + } + } + + /* + else if (CalcType == "FluxHist") { + + weights.resize(NUni, 1.0); + + if (inu >= fluxlist.size()) { + throw cet::exception("FluxHist") + << "inu out of range for fluxlist: inu=" << inu + << " fluxlist.size()=" << fluxlist.size() << "\n"; + } + + if (inu >= mclist.size()) { + throw cet::exception("FluxHist") + << "inu out of range for mclist: inu=" << inu + << " mclist.size()=" << mclist.size() << "\n"; + } + + int parent_pdg = fluxlist[inu].fptype; + int nu_pdg = fluxlist[inu].fntype; + + int idx = GetFluxHistIndex(parent_pdg, nu_pdg); + if (idx < 0 || idx >= 14) { + return weights; + } + + double px = mclist[inu].GetNeutrino().Nu().Px(); + double py = mclist[inu].GetNeutrino().Nu().Py(); + double pz = mclist[inu].GetNeutrino().Nu().Pz(); + + double w = FluxHistWeightCalc(parent_pdg, nu_pdg, px, py, pz); + + // Deterministic event-level correction: same value in every universe slot + for (int i = 0; i < NUni; ++i) { + weights[i] = std::isfinite(w) ? w : 1.0; } } + */ + /* else if (CalcType == "FluxHist") { std::cout << "Entering FluxHist GetWeight for inu = " << inu << std::endl; @@ -392,9 +524,7 @@ namespace sbn { int parent_pdg = fluxlist[inu].fptype; int nu_pdg = fluxlist[inu].fntype; - /* std::cout << " parent PDG = " << parent_pdg - << ", neutrino PDG = " << nu_pdg << std::endl; - */ + int idx = GetFluxHistIndex(parent_pdg, nu_pdg); //std::cout << " FluxHist index = " << idx << std::endl; @@ -436,11 +566,7 @@ namespace sbn { double cv = fCVHist[idx][bin]; double rw = fRWHist[idx][bin]; - /* std::cout << " universe " << i - << ": cv=" << cv - << " rw=" << rw - << " randomN=" << randomN << std::endl; - */ + double w = 1.0; if (cv > 0.0) { @@ -457,46 +583,46 @@ namespace sbn { std::cout << "Leaving FluxHist GetWeight" << std::endl; } - + */ else{//then this must be PrimaryHadron // First let's check that the parent of the neutrino we are looking for is // the particle we intended it to be, if not set all weights to 1 - simb::MCFlux flux; - flux.ftptype = fluxlist[inu].ftptype; - flux.ftpx = fluxlist[inu].ftpx; - flux.ftpy = fluxlist[inu].ftpy; - flux.ftpz = fluxlist[inu].ftpz; - - // If Dk2Nu flux, use ancestors to evaluate tptype - if (fluxlist[inu].fFluxType == simb::kDk2Nu) { - - for( const bsim::Ancestor & ancestor : dk2nu_v->at(inu).ancestor ) { - std::string aproc = ancestor.proc; - if( (aproc.find("BooNEHadronInelastic:BooNEpBeInteraction") != std::string::npos) && (aproc.find("QEBooNE") == std::string::npos) ) { - flux.ftptype = ancestor.pdg; - flux.ftpx = ancestor.startpx; - flux.ftpy = ancestor.startpy; - flux.ftpz = ancestor.startpz; - } // found it - } // find first inelastic - } - - if (std::find(fprimaryHad.begin(), fprimaryHad.end(),(flux.ftptype)) == fprimaryHad.end() ){//if it does not contain any particles we need get 1 + simb::MCFlux flux; + flux.ftptype = fluxlist[inu].ftptype; + flux.ftpx = fluxlist[inu].ftpx; + flux.ftpy = fluxlist[inu].ftpy; + flux.ftpz = fluxlist[inu].ftpz; + + // If Dk2Nu flux, use ancestors to evaluate tptype + if (fluxlist[inu].fFluxType == simb::kDk2Nu) { + + for( const bsim::Ancestor & ancestor : dk2nu_v->at(inu).ancestor ) { + std::string aproc = ancestor.proc; + if( (aproc.find("BooNEHadronInelastic:BooNEpBeInteraction") != std::string::npos) && (aproc.find("QEBooNE") == std::string::npos) ) { + flux.ftptype = ancestor.pdg; + flux.ftpx = ancestor.startpx; + flux.ftpy = ancestor.startpy; + flux.ftpz = ancestor.startpz; + } // found it + } // find first inelastic + } + + if (std::find(fprimaryHad.begin(), fprimaryHad.end(),(flux.ftptype)) == fprimaryHad.end() ){//if it does not contain any particles we need get 1 weights.resize( NUni); - std::fill(weights.begin(), weights.end(), 1); + std::fill(weights.begin(), weights.end(), 1); return weights;//done, all 1 }// Hadronic parent check if(fParameterSet.fRWType == EventWeightParameterSet::kMultiSim){ for (unsigned int i = 0; int(weights.size()) < NUni; i++) {//if all weights are 1, no need to calculate weights; - std::pair test_weight; + std::pair test_weight; - std::vector< float > Vrandom = (fParameterSet.fParameterMap.begin())->second;//vector of random # - std::vector< float > subVrandom;//sub-vector of random numbers; + std::vector< float > Vrandom = (fParameterSet.fParameterMap.begin())->second;//vector of random # + std::vector< float > subVrandom;//sub-vector of random numbers; if( CalcType == "PrimaryHadronNormalization"){//Normalization test_weight = PHNWeightCalc(flux, Vrandom[i]); @@ -516,20 +642,20 @@ namespace sbn { if(test_weight.first){ weights.push_back(test_weight.second); double tmp_weight = test_weight.second; -// std::cout<GetXaxis()->FindBin(px); + int biny = hcv->GetYaxis()->FindBin(py); + int binz = hcv->GetZaxis()->FindBin(pz); + + if (binx < 1) binx = 1; + if (binx > hcv->GetNbinsX()) binx = hcv->GetNbinsX(); + + if (biny < 1) biny = 1; + if (biny > hcv->GetNbinsY()) biny = hcv->GetNbinsY(); + + if (binz < 1) binz = 1; + if (binz > hcv->GetNbinsZ()) binz = hcv->GetNbinsZ(); + + double cv = hcv->GetBinContent(binx, biny, binz); + double rw = hrw->GetBinContent(binx, biny, binz); + + double weight = 1.0; + + if (cv > 0.0) { + weight = rw / cv; + if (!std::isfinite(weight) || weight <= 0.0) { + weight = 1.0; + } + } + + if (debug_counter < 20) { + std::cout << "\n[FluxHist 3D DEBUG]" + << " parent=" << parent_pdg + << " nu=" << nu_pdg + << "\n px=" << px << " binx=" << binx + << "\n py=" << py << " biny=" << biny + << "\n pz=" << pz << " binz=" << binz + << "\n CV=" << cv + << "\n RW=" << rw + << "\n weight=" << weight + << std::endl; + } + + debug_counter++; + + return std::isfinite(weight) ? weight : 1.0; + } + /* + double FluxWeightCalc::FluxHistWeightCalc(int parent_pdg, int nu_pdg, + double px, double py, double pz) + { + static int debug_counter = 0; + + int idx = GetFluxHistIndex(parent_pdg, nu_pdg); + if (idx < 0) return 1.0; + + double comps[3] = {px, py, pz}; + const char* compNames[3] = {"px", "py", "pz"}; + + double log_sum = 0.0; + int n_used = 0; + + if (debug_counter < 20) { + std::cout << "\n[FluxHist DEBUG] Event " << debug_counter + << " parent=" << parent_pdg + << " nu=" << nu_pdg << std::endl; + } + + for (int icomp = 0; icomp < 3; ++icomp) { + TH1* hcv = fCVHist[idx][icomp]; + TH1* hrw = fRWHist[idx][icomp]; + + if (!hcv || !hrw) continue; + + double val = comps[icomp]; + int bin = hcv->GetXaxis()->FindBin(val); + + if (bin < 1) bin = 1; + if (bin > hcv->GetNbinsX()) bin = hcv->GetNbinsX(); + + double cv = hcv->GetBinContent(bin); + double rw = hrw->GetBinContent(bin); + + double ratio = 1.0; + + if (cv > 0.0) { + ratio = rw / cv; + if (!std::isfinite(ratio) || ratio <= 0.0) ratio = 1.0; + } + + + log_sum += std::log(ratio); + n_used++; + + if (debug_counter < 20) { + std::cout << " " << compNames[icomp] + << " = " << val + << " bin=" << bin + << " CV=" << cv + << " RW=" << rw + << " ratio=" << ratio + << std::endl; + } + } + + if (n_used == 0) return 1.0; + + double weight = std::exp(log_sum / n_used); + + if (debug_counter < 20) { + std::cout << " --> FINAL WEIGHT = " << weight << std::endl; + } + + debug_counter++; + + return std::isfinite(weight) ? weight : 1.0; + } + */ + REGISTER_WEIGHTCALC(FluxWeightCalc) } // namespace evwgh } // namespace sbn - diff --git a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.h b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.h index e5fbe4548..45c2b3185 100644 --- a/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.h +++ b/sbncode/SBNEventWeight/Calculators/BNBFlux/FluxCalcPrep.h @@ -16,6 +16,7 @@ //#include //for exit(0); debugging purpose #include "TH1.h" +#include "TH3D.h" #include "TH1F.h" #include "TFile.h" #include "TDecompChol.h"//for Choleskey Decomposition @@ -24,91 +25,117 @@ namespace sbn { namespace evwgh { class FluxWeightCalc : public WeightCalc { - public: - FluxWeightCalc() : WeightCalc() {} - - //Read FHiCL and store the settings for the reweighting environment and the calculator. - void Configure(fhicl::ParameterSet const& p, - CLHEP::HepRandomEngine& engine) override; - - - //GetWeight() returns the final weights as a vector - // each weight evaluaed by *WeightCalc() function; - //inu - the ith parameter. - std::vector GetWeight(art::Event& e, size_t inu) override; - - //UnisimWeightCalc() - Function for evaluating a specific weight - //enu - neutrino energy from simb::MCTruth; - //ptype- parent particles label: pi, k, k0, mu from simb:MCFlux - //ntype - neutrino flavor label: numu, numubar, nue, nuebar from simb:MCFlux - //randomN - input randmo number - //noNeg - determine what formulas to use for weights depending on input histograms. - - //4 *WeightCalc() functions - double UnisimWeightCalc(double enu, int ptype, int ntype, double randomN, bool noNeg);//Unisim - std::pair PHNWeightCalc (simb::MCFlux flux, float rand);//PrimaryHadronNormalizationWeightCalc - std::pair PHFSWeightCalc (simb::MCFlux flux, std::vector rand);//PrimaryHadronFeynmanScaling - std::pair PHSWWeightCalc (simb::MCFlux flux, std::vector rand);//PrimaryHadronSanfordWangWeightCalc - std::pair PHSWCSVWeightCalc(simb::MCFlux flux, std::vector rand);//PrimaryHadronSWCentralSplineVariationWeightCalc + public: + FluxWeightCalc() : WeightCalc() {} + + //Read FHiCL and store the settings for the reweighting environment and the calculator. + void Configure(fhicl::ParameterSet const& p, + CLHEP::HepRandomEngine& engine) override; + + + //GetWeight() returns the final weights as a vector + // each weight evaluaed by *WeightCalc() function; + //inu - the ith parameter. + std::vector GetWeight(art::Event& e, size_t inu) override; + + //UnisimWeightCalc() - Function for evaluating a specific weight + //enu - neutrino energy from simb::MCTruth; + //ptype- parent particles label: pi, k, k0, mu from simb:MCFlux + //ntype - neutrino flavor label: numu, numubar, nue, nuebar from simb:MCFlux + //randomN - input randmo number + //noNeg - determine what formulas to use for weights depending on input histograms. + + //4 *WeightCalc() functions + double UnisimWeightCalc(double enu, int ptype, int ntype, double randomN, bool noNeg);//Unisim + std::pair PHNWeightCalc (simb::MCFlux flux, float rand);//PrimaryHadronNormalizationWeightCalc + std::pair PHFSWeightCalc (simb::MCFlux flux, std::vector rand);//PrimaryHadronFeynmanScaling + std::pair PHSWWeightCalc (simb::MCFlux flux, std::vector rand);//PrimaryHadronSanfordWangWeightCalc + std::pair PHSWCSVWeightCalc(simb::MCFlux flux, std::vector rand);//PrimaryHadronSWCentralSplineVariationWeightCalc - //Handy tool - std::vector ConvertToVector(TArrayD const* array); - - private: - //fParameterSet was prepared in `sbncode/Base/WeightManager.h` - std::string fGeneratorModuleLabel; - std::string CalcType; - - double fScalePos{}; - double fScaleNeg = 1; //for Unisim - - //for Unisim - //load histograms values: [mu/pi/k-/k] x [nue,anue,numu,anumu] x [bin#] - double fCV[4][4][200]; - double fRWpos[4][4][200]; - double fRWneg[4][4][200]; - bool PosOnly{false}; - - //for FluxHist - bool fUseFluxHist = false; - // double fCVHist[7][4][200]; - // double fRWHist[7][4][200]; - - double fCVHist[14][200]{}; - double fRWHist[14][200]{}; - - int GetFluxHistIndex(int parent_pdg, int nu_pdg) const { - if (parent_pdg == 211 && nu_pdg == 14) return 0; - else if (parent_pdg == -211 && nu_pdg == -14) return 1; - else if (parent_pdg == 321 && nu_pdg == 14) return 2; - else if (parent_pdg == -321 && nu_pdg == -14) return 3; - else if (parent_pdg == 130 && nu_pdg == 12) return 4; - else if (parent_pdg == 13 && nu_pdg == 14) return 5; - else if (parent_pdg == -13 && nu_pdg == -14) return 6; - else return -1; - } - //for HadronsProduction - std::vector fprimaryHad = {0}; - //-- FeynmanScaling - std::vector FitVal{};//Shared to SanfordWang - TMatrixD* FitCov{nullptr};//Shared to SanfordWang - - //-- SWCentaralSplineVariation - TMatrixD* HARPXSec{nullptr}; - std::vector HARPmomentumBounds{}; - std::vector HARPthetaBounds{}; - std::vector SWParam{}; - bool fIsDecomposed{false}; - - //Weight Counter - int wc = 0; - int wcn = 0; - int wc0 = 0; - int wc1 = 0; - int wc30 = 0; - - DECLARE_WEIGHTCALC(FluxWeightCalc) - }; + //Handy tool + std::vector ConvertToVector(TArrayD const* array); + + private: + //fParameterSet was prepared in `sbncode/Base/WeightManager.h` + std::string fGeneratorModuleLabel; + std::string CalcType; + + double fScalePos{}; + double fScaleNeg = 1; //for Unisim + + //for Unisim + //load histograms values: [mu/pi/k-/k] x [nue,anue,numu,anumu] x [bin#] + double fCV[4][4][200]; + double fRWpos[4][4][200]; + double fRWneg[4][4][200]; + bool PosOnly{false}; + + //for FluxHist + bool fUseFluxHist = false; + //double fCVHist[7][4][200]; + //double fRWHist[7][4][200]; + + //double fCVHist[14][200]{}; + //double fRWHist[14][200]{}; + + //TH1* fCVHist[14][3]{}; + //TH1* fRWHist[14][3]{}; + + TH3D* fCVHist3D[16]{}; + TH3D* fRWHist3D[16]{}; + + int GetFluxHistIndex(int parent_pdg, int nu_pdg) const { + if (parent_pdg == 211 && nu_pdg == 14) return 0; + else if (parent_pdg == 211 && nu_pdg == 12) return 1; + + else if (parent_pdg == -211 && nu_pdg == -14) return 2; + else if (parent_pdg == -211 && nu_pdg == -12) return 3; + + else if (parent_pdg == 321 && nu_pdg == 14) return 4; + else if (parent_pdg == 321 && nu_pdg == 12) return 5; + + else if (parent_pdg == -321 && nu_pdg == -14) return 6; + else if (parent_pdg == -321 && nu_pdg == -12) return 7; + + else if (parent_pdg == 130 && nu_pdg == 14) return 8; + else if (parent_pdg == 130 && nu_pdg == 12) return 9; + else if (parent_pdg == 130 && nu_pdg == -14) return 10; + else if (parent_pdg == 130 && nu_pdg == -12) return 11; + + else if (parent_pdg == 13 && nu_pdg == 14) return 12; + else if (parent_pdg == 13 && nu_pdg == -12) return 13; + + else if (parent_pdg == -13 && nu_pdg == -14) return 14; + else if (parent_pdg == -13 && nu_pdg == 12) return 15; + + else return -1; + } + + double FluxHistWeightCalc(int parent_pdg, int nu_pdg, + double px, double py, double pz); + + //for HadronsProduction + std::vector fprimaryHad = {0}; + //-- FeynmanScaling + std::vector FitVal{};//Shared to SanfordWang + TMatrixD* FitCov{nullptr};//Shared to SanfordWang + + //-- SWCentaralSplineVariation + TMatrixD* HARPXSec{nullptr}; + std::vector HARPmomentumBounds{}; + std::vector HARPthetaBounds{}; + std::vector SWParam{}; + bool fIsDecomposed{false}; + + //Weight Counter + int wc = 0; + int wcn = 0; + int wc0 = 0; + int wc1 = 0; + int wc30 = 0; + + DECLARE_WEIGHTCALC(FluxWeightCalc) + }; } // namespace evwgh } // namespace sbn diff --git a/sbncode/SBNEventWeight/jobs/flux/eventweight_flux_sbn.fcl b/sbncode/SBNEventWeight/jobs/flux/eventweight_flux_sbn.fcl index 378562279..19650e418 100644 --- a/sbncode/SBNEventWeight/jobs/flux/eventweight_flux_sbn.fcl +++ b/sbncode/SBNEventWeight/jobs/flux/eventweight_flux_sbn.fcl @@ -236,8 +236,8 @@ sbn_eventweight_flux: { calc_type: "FluxHist" -# cv_hist_file: "/exp/sbnd/app/users/rohanr/larsoft_v10_14_02/srcs/sbncode/sbncode/SBNEventWeight/jobs/flux/nuMom_immParent_merged.root" -# rw_hist_file: "/exp/sbnd/app/users/rohanr/larsoft_v10_14_02/srcs/sbncode/sbncode/SBNEventWeight/jobs/flux/nuMom_immParent_oldFiles_correctedName.root" + cv_hist_file: "/pnfs/sbnd/scratch/users/rohanr/beamweight/final_hists/nuMom_immParent_merged_200.root" + rw_hist_file: "/pnfs/sbnd/scratch/users/rohanr/beamweight/final_hists/nuMom_immParent_oldFiles_200_merged.root" scale_factor_pos: 1 } From 0e2f2754dd48c0fa89de2cafc40824b34242f4d7 Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Wed, 29 Apr 2026 15:21:03 +0200 Subject: [PATCH 08/14] Delete sbncode/EventGenerator/MeVPrtl/Tools/DP directory Not intended to be part of branch --- .../MeVPrtl/Tools/DP/CMakeLists.txt | 50 -- .../MeVPrtl/Tools/DP/DPDecay_tool.cc | 502 ------------------ .../MeVPrtl/Tools/DP/Meson2DP_tool.cc | 204 ------- .../MeVPrtl/Tools/DP/old/CMakeLists.txt | 68 --- .../MeVPrtl/Tools/DP/old/DPMakeDecay_tool.cc | 239 --------- .../MeVPrtl/Tools/DP/old/Eta2DPFlux_tool.cc | 231 -------- .../Tools/DP/old/PiZero2DPFlux_tool.cc | 275 ---------- 7 files changed, 1569 deletions(-) delete mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/CMakeLists.txt delete mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/DPDecay_tool.cc delete mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc delete mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/old/CMakeLists.txt delete mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/old/DPMakeDecay_tool.cc delete mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/old/Eta2DPFlux_tool.cc delete mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/DP/old/PiZero2DPFlux_tool.cc diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/CMakeLists.txt b/sbncode/EventGenerator/MeVPrtl/Tools/DP/CMakeLists.txt deleted file mode 100644 index 0f40c1184..000000000 --- a/sbncode/EventGenerator/MeVPrtl/Tools/DP/CMakeLists.txt +++ /dev/null @@ -1,50 +0,0 @@ - -cet_build_plugin( DPDecay art::tool - LIBRARIES - ifdh_art::IFDH_service - art::Framework_Core - art::Framework_Services_Registry - art_root_io::TFileService_service - art::Framework_Principal - art::Persistency_Common - art::Utilities canvas::canvas - cetlib::cetlib cetlib_except::cetlib_except - ROOT::EGPythia6 - CLHEP::CLHEP - sbnobj::Common_EventGen_MeVPrtl - nugen::EventGeneratorBase_GENIE - nusimdata::SimulationBase - nurandom::RandomUtils_NuRandomService_service - GSL::gsl - sbncode_EventGenerator_MeVPrtl_Constants - sbnobj::Common_EventGen_MeVPrtl - -) -cet_build_plugin( Meson2DP art::tool - LIBRARIES - art::Framework_Core - art::Framework_Services_Registry - art_root_io::TFileService_service - art::Framework_Principal - art::Persistency_Common - art::Utilities canvas::canvas - cetlib::cetlib cetlib_except::cetlib_except - ROOT::EGPythia6 - CLHEP::CLHEP - sbnobj::Common_EventGen_MeVPrtl - nugen::EventGeneratorBase_GENIE - nusimdata::SimulationBase - nurandom::RandomUtils_NuRandomService_service - GSL::gsl - sbncode_EventGenerator_MeVPrtl_Constants - sbnobj::Common_EventGen_MeVPrtl -) - - - - -add_subdirectory(old) - -install_headers() -install_fhicl() -install_source() diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/DPDecay_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/DP/DPDecay_tool.cc deleted file mode 100644 index ce8a35fbc..000000000 --- a/sbncode/EventGenerator/MeVPrtl/Tools/DP/DPDecay_tool.cc +++ /dev/null @@ -1,502 +0,0 @@ -#include "cetlib/search_path.h" -#include "cetlib_except/exception.h" -#include "ifdh_art/IFDHService/IFDH_service.h" - -#include "art/Framework/Services/Registry/ServiceHandle.h" - -#include -#include - -#include "art/Utilities/ToolMacros.h" -#include "fhiclcpp/ParameterSet.h" -#include "messagefacility/MessageLogger/MessageLogger.h" - -#include "sbncode/EventGenerator/MeVPrtl/Tools/IMeVPrtlDecay.h" -#include "sbncode/EventGenerator/MeVPrtl/Tools/Constants.h" -#include "sbnobj/Common/EventGen/MeVPrtl/MeVPrtlFlux.h" - -#include "CLHEP/Random/RandFlat.h" - -#include -#include -#include -#include -#include - -namespace evgen { -namespace ldm { - -namespace { - -double flat_to_exp_rand(double x, double mean, double a, double b) { - const double A = (1. - std::exp(-(b-a)/mean)); - return - mean * std::log(1 - x * A) + a; -} - -double forcedecay_weight(double mean, double a, double b) { - return std::exp(-a/mean) - std::exp(-b/mean); -} - - -} // anon - -class DPDecay : public IMeVPrtlDecay { -public: - DPDecay(fhicl::ParameterSet const& pset); - ~DPDecay() override = default; - - void configure(fhicl::ParameterSet const& pset) override; - - bool Decay(const MeVPrtlFlux& flux, - const TVector3& in, - const TVector3& out, - MeVPrtlDecay& decay, - double& weight) override; - - - double MaxWeight() override { return fMaxWeight; } - -private: - bool fAllowElectronDecay = true; - bool fAllowMuonDecay = true; - bool fAddTimeOfFlight = true; - bool fVerbose = false; - - // FHiCL inputs - // double fCTau_cm = 1.0; - // double fBR_ee = 1.0; - double fEpsilon = -1.0; - - std::vector fRequestedTableFiles; - std::string fTableSearchPath; - std::string fTableCopyMethod; - bool fUseIFDHForTables = false; - std::vector fBRTables; - - std::vector fMassGridE; - std::vector fMassGridMu; - std::vector fMassGridHad; - - std::vector fBRHad; - std::vector fBRMu; - std::vector fBRE; - - double fReferenceRayLength = -1; - double fReferenceRayDistance = 0.; - double fReferenceMass = -1; - double fReferenceCTau_cm = -1; - double fReferenceEnergy = -1; - - double fMaxWeight = -1.; - double interp(const std::vector& x, - const std::vector& y, - double val) const; - - double Gamma_ll(double m, double eps, double ml) const; - - double Gamma_total(double m, double eps) const; - - std::vector LoadTableFiles(); - void ReadTableFile(const std::string& fname, - std::vector& masses, - std::vector& vals) const; - -}; - /* - auto load_table = [](const std::string& fname, - std::vector& m, - std::vector& br) { - std::ifstream f(fname); - double x, y; - while (f >> x >> y) { - m.push_back(x); - br.push_back(y); - } - };*/ - - -DPDecay::DPDecay(fhicl::ParameterSet const& pset) - : IMeVPrtlStage("DPDecay") -{ - configure(pset); - fBRTables = LoadTableFiles(); - if (fBRTables.size() != 3) { - throw cet::exception("DPDecay") - << "Expected exactly 3 resolved table files, got " - << fBRTables.size() << ".\n"; - } - - ReadTableFile(fBRTables[0], fMassGridE, fBRE); - ReadTableFile(fBRTables[1], fMassGridMu, fBRMu); - ReadTableFile(fBRTables[2], fMassGridHad, fBRHad); - - if (fVerbose) { - mf::LogInfo("DPDecay") - << "Loaded table[0]: " << fBRTables[0] - << " with " << fBRE.size() << " rows\n" - << "Loaded table[1]: " << fBRTables[1] - << " with " << fBRMu.size() << " rows\n" - << "Loaded table[2]: " << fBRTables[2] - << " with " << fBRHad.size() << " rows"; - } -} - -void DPDecay::configure(fhicl::ParameterSet const& pset) -{ - fAllowElectronDecay = pset.get("AllowElectronDecay", true); - fAllowMuonDecay = pset.get("AllowMuonDecay", true); - fAddTimeOfFlight = pset.get("AddTimeOfFlight", true); - fVerbose = pset.get("Verbose", false); - fEpsilon = pset.get("Epsilon"); - //fCTau_cm = pset.get("CTau_cm"); - //fBR_ee = pset.get("BR_ee"); - - /* - if (fCTau_cm <= 0.0) { - throw cet::exception("DPDecay") << "CTau_cm must be > 0."; - } - fBR_ee = std::clamp(fBR_ee, 0.0, 1.0); -*/ - fReferenceRayLength = pset.get("ReferenceRayLength", -1.0); - fReferenceRayDistance = pset.get("ReferenceRayDistance", 0.0); - fReferenceMass = pset.get("ReferenceMass", -1.0); - fReferenceCTau_cm = pset.get("ReferenceCTau_cm", -1.0); - fReferenceEnergy = pset.get("ReferenceEnergy", -1.0); - - fRequestedTableFiles = pset.get>("TableFiles"); - fTableSearchPath = pset.get("TableSearchPath", ""); - fTableCopyMethod = pset.get("TableCopyMethod", "DIRECT"); - fUseIFDHForTables = pset.get("UseIFDHForTables", false); - - if (fRequestedTableFiles.size() != 3) { - throw cet::exception("DPDecay") - << "FHiCL parameter TableFiles must contain exactly 3 entries " - << "(ee, mu_mu, hadrons). Got " - << fRequestedTableFiles.size() << ".\n"; - } - - if (fVerbose) { - mf::LogInfo("DPDecay") - << "Configured DPDecay with table files:\n" - << " [0] " << fRequestedTableFiles[0] << "\n" - << " [1] " << fRequestedTableFiles[1] << "\n" - << " [2] " << fRequestedTableFiles[2] << "\n" - << "UseIFDHForTables = " << fUseIFDHForTables << "\n" - << "TableCopyMethod = " << fTableCopyMethod << "\n" - << "TableSearchPath = " << fTableSearchPath; - } - - /* - load_table("bfrac_dark_photon_e_e.txt", fMassGrid, fBRE); - load_table("bfrac_dark_photon_mu_mu.txt", fMassGrid, fBRMu); - load_table("bfrac_dark_photon_hadrons.txt", fMassGrid, fBRHad); - */ - if (fReferenceRayLength > 0 && fReferenceMass > 0 && fReferenceCTau_cm > 0 && fReferenceEnergy > 0) { - const double mS = fReferenceMass; - - const double p = std::sqrt(std::max(0.0, fReferenceEnergy*fReferenceEnergy - mS*mS)); - const double gamma_beta = (mS > 0) ? (p / mS) : 0.0; - - const double mean_dist = fReferenceCTau_cm * gamma_beta; - if (mean_dist <= 0) { fMaxWeight = 0.0; return; } - - fMaxWeight = forcedecay_weight(mean_dist, fReferenceRayDistance, - fReferenceRayDistance + fReferenceRayLength); - } else { - fMaxWeight = -1.; - } -} - std::vector DPDecay::LoadTableFiles() - { - std::vector files; - files.reserve(fRequestedTableFiles.size()); - - // Case 1: use IFDH similarly to BNBKaonGen - if (fUseIFDHForTables) { - art::ServiceHandle ifdhp; - - std::vector> selected; - selected.reserve(fRequestedTableFiles.size()); - - for (const auto& pattern : fRequestedTableFiles) { - std::vector> found = - ifdhp->findMatchingFiles(fTableSearchPath, pattern); - - if (found.empty()) { - throw cet::exception("DPDecay") - << "LoadTableFiles: no match found for pattern '" - << pattern << "' in search path '" - << fTableSearchPath << "'.\n"; - } - - if (found.size() > 1) { - throw cet::exception("DPDecay") - << "LoadTableFiles: multiple matches found for pattern '" - << pattern << "' in search path '" - << fTableSearchPath << "'. " - << "Use a more specific filename/pattern.\n"; - } - - selected.push_back(found[0]); - } - - if (fTableCopyMethod == "DIRECT") { - for (const auto& f : selected) { - files.push_back(f.first); - } - return files; - } - - std::vector> localFiles = - ifdhp->fetchSharedFiles(selected, fTableCopyMethod); - - if (localFiles.size() != selected.size()) { - throw cet::exception("DPDecay") - << "LoadTableFiles: requested " << selected.size() - << " files, but fetched " << localFiles.size() << ".\n"; - } - - for (const auto& f : localFiles) { - files.push_back(f.first); - } - - return files; - } - - // Case 2: exact/local files or FW_SEARCH_PATH resolution - cet::search_path sp("FW_SEARCH_PATH"); - - for (const auto& requested : fRequestedTableFiles) { - std::string resolved = requested; - - // First try opening exactly as given - { - std::ifstream test(requested); - if (test.good()) { - files.push_back(requested); - continue; - } - } - - // Then try FW_SEARCH_PATH - if (!sp.find_file(requested, resolved)) { - char const* fw = std::getenv("FW_SEARCH_PATH"); - throw cet::exception("DPDecay") - << "LoadTableFiles: could not find table file '" - << requested - << "' either directly or via FW_SEARCH_PATH.\n" - << "FW_SEARCH_PATH is: " << (fw ? fw : "") << "\n"; - } - - files.push_back(resolved); - } - - return files; - } - - void DPDecay::ReadTableFile(const std::string& fname, - std::vector& masses, - std::vector& vals) const - { - masses.clear(); - vals.clear(); - - std::ifstream f(fname); - if (!f.is_open()) { - throw cet::exception("DPDecay") - << "ReadTableFile: failed to open file '" << fname << "'.\n"; - } - - double x, y; - while (f >> x >> y) { - masses.push_back(x); - vals.push_back(y); - } - - if (f.bad()) { - throw cet::exception("DPDecay") - << "ReadTableFile: I/O error while reading '" << fname << "'.\n"; - } - - if (masses.empty()) { - throw cet::exception("DPDecay") - << "ReadTableFile: file '" << fname << "' had no valid rows.\n"; - } - - if (masses.size() != vals.size()) { - throw cet::exception("DPDecay") - << "ReadTableFile: inconsistent table lengths in '" << fname << "'.\n"; - } - - for (size_t i = 1; i < masses.size(); ++i) { - if (masses[i] < masses[i-1]) { - throw cet::exception("DPDecay") - << "ReadTableFile: mass grid in '" << fname - << "' is not sorted ascending at row " << i << ".\n"; - } - } - } - - double DPDecay::interp(const std::vector& x, - const std::vector& y, - double val) const { - int idx = 0; - double best = 1e9; - for (size_t i = 0; i < x.size(); i++) { - double d = std::abs(x[i] - val); - if (d < best) { best = d; idx = i; } - } - return y[idx]; - } - double DPDecay::Gamma_ll(double m, double eps, double ml) const { - const double alpha = 1.0/137.0; - if (m <= 2*ml) return 0.0; - - double beta = std::sqrt(1 - 4*ml*ml/(m*m)); - return (1.0/3.0) * alpha * eps*eps * m * - (1 + 2*ml*ml/(m*m)) * beta; - } - double DPDecay::Gamma_total(double m, double eps) const { - if (m < 0.29) { - return Gamma_ll(m, eps, 0.000511) + - Gamma_ll(m, eps, 0.105); - } else { - double br_mu = interp(fMassGridMu, fBRMu, m); - double gmu = Gamma_ll(m, eps, 0.105); - return (br_mu > 0) ? gmu / br_mu : 0.0; - } - } - -bool DPDecay::Decay(const MeVPrtlFlux& flux, - const TVector3& in, - const TVector3& out, - MeVPrtlDecay& decay, - double& weight) -{ - const auto& C = Constants::Instance(); - - const double mS = flux.mass; - if (!(mS > 0.0)) return false; - - if (mS <= 2.0 * C.elec_mass) { - throw cet::exception("DPDecay") - << "BAD MASS: mS=" << mS << " below 2*me threshold."; - } - - /* - const bool ee_open = fAllowElectronDecay && (mS > 2.0*C.elec_mass); - const bool mumu_open = fAllowMuonDecay && (mS > 2.0*C.muon_mass); - - if (!ee_open && !mumu_open) return false; - - double br_e = 0.0; - double br_mu = 0.0; - - if (ee_open && mumu_open) { - br_e = fBR_ee; - br_mu = 1.0 - fBR_ee; - } else if (ee_open) { - // mu closed -> force ee - br_e = 1.0; - br_mu = 0.0; - } else { - // ee closed (shouldn't happen if mS>2me) -> force mu - br_e = 0.0; - br_mu = 1.0; - } - */ - // mean lab decay distance [cm] - // const double mean_dist = fCTau_cm * flux.mom.Gamma() * flux.mom.Beta(); - - const double mA = flux.mass; - const double Gamma = Gamma_total(mA, fEpsilon); - - double Gamma_ee = Gamma_ll(mA, fEpsilon, 0.000511); - double BR_ee = Gamma_ee / Gamma; - - if (Gamma <= 0) return false; - - // hbar*c in GeV*cm - const double hbarc = 1.973e-14; - - double ctau_cm = hbarc / Gamma; - - const double mean_dist = ctau_cm * flux.mom.Gamma() * flux.mom.Beta(); - if (mean_dist <= 0.0) return false; - - const double in_dist = (flux.pos.Vect() - in ).Mag(); - const double out_dist = (flux.pos.Vect() - out).Mag(); - - weight = forcedecay_weight(mean_dist, in_dist, out_dist); - weight *= BR_ee; - if (weight == 0.0) return false; - - - // pick channel by BR - /* const double u = CLHEP::RandFlat::shoot(fEngine, 0.0, 1.0); - const int ch = pick_by_br(br_e, br_mu, u); - if (ch < 0) return false; - */ - const int abs_pdg = 11; - const double ml = C.elec_mass; - - // sample decay point along ray within [in,out] - const double u2 = CLHEP::RandFlat::shoot(fEngine, 0.0, 1.0); - const double decay_rand = flat_to_exp_rand(u2, mean_dist, in_dist, out_dist); - TVector3 decay_pos3 = flux.pos.Vect() + decay_rand * (in - flux.pos.Vect()).Unit(); - - const double decay_time = fAddTimeOfFlight ? TimeOfFlight(flux, decay_pos3) : flux.pos.T(); - TLorentzVector decay_pos(decay_pos3, decay_time); - - // 2-body kinematics in S rest frame - const double E_rf = mS / 2.0; - const double p_rf = std::sqrt(std::max(0.0, E_rf*E_rf - ml*ml)); - - TVector3 pA_rf = RandomUnitVector() * p_rf; - TVector3 pB_rf = -pA_rf; - - TLorentzVector p4A(pA_rf, E_rf); - TLorentzVector p4B(pB_rf, E_rf); - - p4A.Boost(flux.mom.BoostVector()); - p4B.Boost(flux.mom.BoostVector()); - - - //const double tau_ns = fCTau_cm / C.c_cm_per_ns; - double tau_ns = (ctau_cm > 0) ? (ctau_cm / C.c_cm_per_ns) : 0.0; - const double gamma_tot = (tau_ns > 0) ? (C.hbar / tau_ns) : 0.0; - - decay.total_decay_width = gamma_tot; - decay.total_mean_lifetime = tau_ns; - decay.total_mean_distance = mean_dist; - decay.allowed_decay_fraction = 1.0; - - decay.pos = decay_pos; - - decay.daughter_mom.clear(); - decay.daughter_e.clear(); - decay.daughter_pdg.clear(); - - decay.daughter_mom.push_back(p4A.Vect()); - decay.daughter_e.push_back(p4A.E()); - decay.daughter_pdg.push_back(+abs_pdg); - - decay.daughter_mom.push_back(p4B.Vect()); - decay.daughter_e.push_back(p4B.E()); - decay.daughter_pdg.push_back(-abs_pdg); - - if (fVerbose) { - mf::LogInfo("DPDecay") - << "mS=" << mS - << " BR_ee(eff)=" << BR_ee - << " mean_dist_cm=" << mean_dist - << " weight=" << weight; - } - - return true; -} - -DEFINE_ART_CLASS_TOOL(DPDecay) - -} // namespace ldm -} // namespace evgen diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc deleted file mode 100644 index 539e5abb7..000000000 --- a/sbncode/EventGenerator/MeVPrtl/Tools/DP/Meson2DP_tool.cc +++ /dev/null @@ -1,204 +0,0 @@ - - -#include "art/Utilities/ToolMacros.h" -#include "fhiclcpp/ParameterSet.h" -#include "messagefacility/MessageLogger/MessageLogger.h" - -#include "sbncode/EventGenerator/MeVPrtl/Tools/IMeVPrtlFlux.h" -#include "sbnobj/Common/EventGen/MeVPrtl/MeVPrtlFlux.h" -#include "sbnobj/Common/EventGen/MeVPrtl/MesonParent.h" - -#include "TDatabasePDG.h" -#include "TParticlePDG.h" - -#include -#include -#include -#include - -namespace evgen { -namespace ldm { - -class Meson2DP : public IMeVPrtlFlux { -public: - Meson2DP(fhicl::ParameterSet const& pset); - ~Meson2DP() override = default; - - void configure(fhicl::ParameterSet const& pset) override; - bool MakeFlux(const simb::MCFlux& flux, MeVPrtlFlux& dp, double& weight) override; - - double MaxWeight() override { return 1.0; } - -private: - double fM = 0.0; - double fe = 0.0; - - bool fVerbose = false; - - std::vector fParents; - bool fCorrectDK2NU = true; - - std::string fSecondarySignConvention = "legacy"; // legacy/physical - - static double pdg_mass_GeV(int pdg) { - auto* db = TDatabasePDG::Instance(); - TParticlePDG* p = db->GetParticle(pdg); - return p ? p->Mass() : -1.0; - } - - static double BRMeson2SM(int pdg){ - - if (pdg == 221){ - return 0.39; - } - else if (pdg == 111){ - return 0.99; - } - return 0.0; - } - - static double BRMeson2DP(int pdg, double e, double mA){ - - double m_meson = pdg_mass_GeV(pdg); - double temp1 = 2*e*e; - double temp2 = 1-((mA*mA)/(m_meson*m_meson)); - double br = BRMeson2SM(pdg); - double br_dp = temp1*temp2*br; - - return br_dp; - - } - - static double twobody_momentum(double M, double m1, double m2) { - if (M < m1 + m2) return -1.0; - const double a = M*M - (m1+m2)*(m1+m2); - const double b = M*M - (m1-m2)*(m1-m2); - if (a < 0 || b < 0) return -1.0; - return std::sqrt(a*b) / (2.0*M); - } - - - bool parent_allowed(int abs_pdg) const { - for (int p : fParents) if (abs_pdg == std::abs(p)) return true; - return false; - } -}; - -Meson2DP::Meson2DP(fhicl::ParameterSet const& pset) - : IMeVPrtlStage("Meson2DP") - , IMeVPrtlFlux(pset) -{ - configure(pset); -} - -void Meson2DP::configure(fhicl::ParameterSet const& pset) -{ - fM = pset.get("M"); - fe = pset.get("e"); - - fVerbose = pset.get("Verbose", false); - - fParents = pset.get>("Parents", std::vector{321}); // default K± - fCorrectDK2NU = pset.get("CorrectDK2NU", true); - - fSecondarySignConvention = - pset.get("SecondarySignConvention", "legacy"); - std::transform(fSecondarySignConvention.begin(), fSecondarySignConvention.end(), - fSecondarySignConvention.begin(), ::tolower); -} - -bool Meson2DP::MakeFlux(const simb::MCFlux& flux, - evgen::ldm::MeVPrtlFlux& dp, - double& weight) -{ - evgen::ldm::MesonParent parent(flux); - - const int mpdg = parent.meson_pdg; - const int abs_mpdg = std::abs(mpdg); - - if (!parent_allowed(abs_mpdg)) return false; - - - if (abs_mpdg != 221) return false; // eta only - - const double mA = fM; - if (!(mA > 0.0)) return false; - - const double e = fe; - if (!(e > 0.0)) return false; - - - double br = BRMeson2DP(abs_mpdg, e, mA); - if (!(br > 0.0)) return false; - if (br > 1.0) { - if (fVerbose) mf::LogWarning("Meson2DP") << "BRprod>1 (" << br << "), capping to 1."; - br = 1.0; - } - - - TLorentzVector Beam4 = BeamOrigin(); - dp.pos_beamcoord = parent.pos; - dp.pos = parent.pos; - dp.pos.Transform(fBeam2Det); - dp.pos += Beam4; - - dp.mmom_beamcoord = parent.mom; - dp.mmom = parent.mom; - dp.mmom.Transform(fBeam2Det); - - - const int gamma_pdg = 22; - - const double mMeson = pdg_mass_GeV(221); - const double mgamma = 0.0; - - const double pstar = twobody_momentum(mMeson, mgamma, mA); - if (pstar < 0) return false; - - const double eA = std::sqrt(pstar*pstar + mA*mA); - - // isotropic S in K rest frame - dp.mom = TLorentzVector(pstar * RandomUnitVector(), eA); - - // boost to lab - TLorentzVector mom_lab = dp.mom; - mom_lab.Boost(parent.mom.BoostVector()); - - dp.mom_beamcoord = mom_lab; - dp.mom = mom_lab; - dp.mom.Transform(fBeam2Det); - - dp.sec_beamcoord = dp.mmom_beamcoord - dp.mom_beamcoord; - dp.sec = dp.mmom - dp.mom; - - double denom = 1.0; - - weight = parent.weight * br / denom; - if (weight == 0.0) return false; - - dp.mass = mA; - dp.meson_pdg = mpdg; - dp.secondary_pdg = gamma_pdg; - - dp.generator = 1; - dp.equiv_enu = EnuLab(flux.fnecm, dp.mmom, dp.pos); - - - dp.C1 = 0.0; dp.C2 = 0.0; dp.C3 = 0.0; dp.C4 = 0.0; dp.C5 = 0.0; - - if (fVerbose) { - mf::LogInfo("Meson2DP") - << "parent=" << mpdg - << " mA=" << mA - << " BRprod=" << br - << " denom=" << denom - << " weight=" << weight; - } - - return true; -} - -DEFINE_ART_CLASS_TOOL(Meson2DP) - -} // namespace ldm -} // namespace evgen diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/CMakeLists.txt b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/CMakeLists.txt deleted file mode 100644 index 77830b4ad..000000000 --- a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/CMakeLists.txt +++ /dev/null @@ -1,68 +0,0 @@ - -cet_build_plugin( PiZero2DPFlux art::tool - LIBRARIES - art::Framework_Core - art::Framework_Services_Registry - art_root_io::TFileService_service - art::Framework_Principal - art::Persistency_Common - art::Utilities canvas::canvas - cetlib::cetlib cetlib_except::cetlib_except - ROOT::EGPythia6 - CLHEP::CLHEP - sbnobj::Common_EventGen_MeVPrtl - nugen::EventGeneratorBase_GENIE - nusimdata::SimulationBase - nurandom::RandomUtils_NuRandomService_service - GSL::gsl - sbncode_EventGenerator_MeVPrtl_Constants - sbnobj::Common_EventGen_MeVPrtl -) - - -cet_build_plugin( Eta2DPFlux art::tool - LIBRARIES - art::Framework_Core - art::Framework_Services_Registry - art_root_io::TFileService_service - art::Framework_Principal - art::Persistency_Common - art::Utilities canvas::canvas - cetlib::cetlib cetlib_except::cetlib_except - CLHEP::CLHEP - nurandom::RandomUtils_NuRandomService_service - nusimdata::SimulationBase - GSL::gsl - larcorealg::Geometry - sbncode_EventGenerator_MeVPrtl_Dalitz - sbncode_EventGenerator_MeVPrtl_AnThreeBD - sbncode_EventGenerator_MeVPrtl_Constants - sbnobj::Common_EventGen_MeVPrtl - nugen::EventGeneratorBase_GENIE -) - -cet_build_plugin( DPMakeDecay art::tool - LIBRARIES - art::Framework_Core - art::Framework_Services_Registry - art_root_io::TFileService_service - art::Framework_Principal - art::Persistency_Common - art::Utilities canvas::canvas - cetlib::cetlib cetlib_except::cetlib_except - CLHEP::CLHEP - nurandom::RandomUtils_NuRandomService_service - nusimdata::SimulationBase - GSL::gsl - larcorealg::Geometry - sbncode_EventGenerator_MeVPrtl_Dalitz - sbncode_EventGenerator_MeVPrtl_AnThreeBD - sbncode_EventGenerator_MeVPrtl_AnTwoBD - sbncode_EventGenerator_MeVPrtl_Constants - sbnobj::Common_EventGen_MeVPrtl -) - - -install_headers() -install_fhicl() -install_source() diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/DPMakeDecay_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/DPMakeDecay_tool.cc deleted file mode 100644 index 58cdeff0c..000000000 --- a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/DPMakeDecay_tool.cc +++ /dev/null @@ -1,239 +0,0 @@ -/** - * Dark Photon Decay Tool - */ - -#include "art/Framework/Core/EDProducer.h" -#include "art/Framework/Principal/Event.h" -#include "art/Framework/Principal/Handle.h" -#include "art/Framework/Services/Registry/ServiceHandle.h" -#include "art/Persistency/Common/PtrMaker.h" -#include "art/Utilities/ToolMacros.h" -#include "cetlib/cpu_timer.h" -#include "fhiclcpp/ParameterSet.h" -#include "messagefacility/MessageLogger/MessageLogger.h" - - -#include "sbnobj/Common/EventGen/MeVPrtl/MeVPrtlFlux.h" -#include "sbncode/EventGenerator/MeVPrtl/Tools/IMeVPrtlDecay.h" -#include "sbncode/EventGenerator/MeVPrtl/Tools/Constants.h" - -#include "CLHEP/Random/RandFlat.h" -#include "TDatabasePDG.h" - -#include -#include -#include -#include - -namespace evgen { - namespace ldm { - - class DPMakeDecay : public IMeVPrtlDecay { - - public: - DPMakeDecay(fhicl::ParameterSet const &pset); - ~DPMakeDecay() {} - - void configure(fhicl::ParameterSet const &pset) override; - - bool Decay(const MeVPrtlFlux &flux, - const TVector3 &in, - const TVector3 &out, - MeVPrtlDecay &decay, - double &weight) override; - - double MaxWeight() override { return 1.0; } - - private: - - double fEpsilon; - bool fVerbose; - - std::vector fMassBR; - std::vector fBRElec; - std::vector fBRHad; - std::vector fBRMu; - - double AlphaEM() const { return 1.0/137.0; } - - double GammaLL(double m, double mlep) const { - if (m <= 2*mlep) return 0.0; - - double coupsq = fEpsilon*fEpsilon*AlphaEM(); - return (coupsq/3.0)*m* - (1 + 2*mlep*mlep/(m*m))* - std::sqrt(1 - 4*mlep*mlep/(m*m)); - } - - double InterpBR(const std::vector& mass, - const std::vector& br, - double m) const { - - if (mass.empty()) return 0.0; - - size_t best = 0; - double mindiff = std::abs(mass[0] - m); - - for (size_t i=1;i 0) - return gamma_mu / br_mu; - - return GammaLL(m, me); - } - - }; - - DPMakeDecay::DPMakeDecay(fhicl::ParameterSet const &pset) - : IMeVPrtlStage("DPMakeDecay") - { - configure(pset); - } - - void DPMakeDecay::configure(fhicl::ParameterSet const &pset) - { - fVerbose = pset.get("Verbose", false); - fEpsilon = pset.get("Epsilon"); - - std::string file_ee = "/pnfs/sbnd/persistent/users/rohanr/dp/br/bfrac_dark_photon_e_e.txt"; - std::string file_had = "/pnfs/sbnd/persistent/users/rohanr/dp/br/bfrac_dark_photon_hadrons.txt"; - std::string file_mu = "/pnfs/sbnd/persistent/users/rohanr/dp/br/bfrac_dark_photon_mu_mu.txt"; - - std::ifstream eefile(file_ee); - std::ifstream hadfile(file_had); - std::ifstream mufile(file_mu); - - double m, br; - - while (eefile >> m >> br) { - fMassBR.push_back(m); - fBRElec.push_back(br); - } - - while (hadfile >> m >> br) { - fMassBR.push_back(m); - fBRHad.push_back(br); - } - - while (mufile >> m >> br) { - fBRMu.push_back(br); - } - - if (fVerbose) - std::cout << "Loaded Dark Photon BR tables." << std::endl; - } - - bool DPMakeDecay::Decay(const MeVPrtlFlux &flux, - const TVector3 &in, - const TVector3 &out, - MeVPrtlDecay &decay, - double &weight) - { - double m = flux.mass; - - double total_width = TotalWidth(m); - if (total_width == 0) return false; - - double lifetime_ns = Constants::Instance().hbar / total_width; - double mean_dist = lifetime_ns * - flux.mom.Gamma() * - flux.mom.Beta() * - Constants::Instance().c_cm_per_ns; - - double in_dist = (flux.pos.Vect() - in).Mag(); - double out_dist = (flux.pos.Vect() - out).Mag(); - - double forced_weight = - std::exp(-in_dist/mean_dist) - - std::exp(-out_dist/mean_dist); - - weight = forced_weight; - - if (weight <= 0) return false; - - double me = Constants::Instance().elec_mass; - // double mmu = Constants::Instance().muon_mass; - - /* - double gamma_ee = GammaLL(m, me); - double gamma_mumu = GammaLL(m, mmu); - - double r = CLHEP::RandFlat::shoot(fEngine); - - bool decay_to_mu = false; - if (gamma_mumu > 0 && - r < gamma_mumu / total_width) - decay_to_mu = true; - - double mlep = decay_to_mu ? mmu : me; - int pdg = decay_to_mu ? 13 : 11; - */ - - double gamma_ee = GammaLL(m, me); - - double br_ee = gamma_ee / total_width; - weight *= br_ee; - - double mlep = me; - int pdg = 11; - double p = std::sqrt(m*m/4. - mlep*mlep); - - TVector3 dir = RandomUnitVector(); - - TLorentzVector lplus( p*dir, std::sqrt(p*p + mlep*mlep) ); - TLorentzVector lminus(-p*dir, std::sqrt(p*p + mlep*mlep) ); - - lplus.Boost(flux.mom.BoostVector()); - lminus.Boost(flux.mom.BoostVector()); - - double flat = CLHEP::RandFlat::shoot(fEngine,0,1); - double decay_dist = -mean_dist*std::log(1-flat); - - TVector3 decay_pos = - flux.pos.Vect() + - decay_dist * (in - flux.pos.Vect()).Unit(); - - decay.pos = TLorentzVector(decay_pos, - TimeOfFlight(flux, decay_pos)); - - decay.daughter_mom.push_back(lplus.Vect()); - decay.daughter_e.push_back(lplus.E()); - decay.daughter_pdg.push_back(-pdg); - - decay.daughter_mom.push_back(lminus.Vect()); - decay.daughter_e.push_back(lminus.E()); - decay.daughter_pdg.push_back(pdg); - - decay.total_decay_width = total_width; - decay.total_mean_lifetime = lifetime_ns; - decay.total_mean_distance = mean_dist; - decay.allowed_decay_fraction = 1.0; - - return true; - } - - DEFINE_ART_CLASS_TOOL(DPMakeDecay) - - } // namespace ldm -} // namespace evgen diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/Eta2DPFlux_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/Eta2DPFlux_tool.cc deleted file mode 100644 index e807663d3..000000000 --- a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/Eta2DPFlux_tool.cc +++ /dev/null @@ -1,231 +0,0 @@ -/** - * - */ - -// Framework Includes -#include "art/Framework/Core/EDProducer.h" -#include "art/Framework/Principal/Event.h" -#include "art/Framework/Principal/Handle.h" -#include "art/Framework/Services/Registry/ServiceHandle.h" -#include "art/Persistency/Common/PtrMaker.h" -#include "art/Utilities/ToolMacros.h" -#include "cetlib/cpu_timer.h" -#include "fhiclcpp/ParameterSet.h" -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "CLHEP/Random/RandFlat.h" - -// local includes -#include "sbncode/EventGenerator/MeVPrtl/Tools/IMeVPrtlFlux.h" -#include "sbncode/EventGenerator/MeVPrtl/Tools/Constants.h" - -#include "sbnobj/Common/EventGen/MeVPrtl/MeVPrtlFlux.h" -#include "sbnobj/Common/EventGen/MeVPrtl/MesonParent.h" - -// ROOT -#include "TVector3.h" - -// std includes -#include -#include -#include - -#include "TDatabasePDG.h" - -//------------------------------------------------------------------------------------------------------------------------------------------ -// implementation follows - -namespace evgen { -namespace ldm { -/** - * @brief Tau2HNLFlux class definiton - * - * Implementation of Kaon->HNL branching ratio taken from: - * arXiv:1912.07622 - */ -class Tau2HNLFlux : public IMeVPrtlFlux -{ -public: - /** - * @brief Constructor - */ - Tau2HNLFlux(fhicl::ParameterSet const &pset); - - /** - * @brief Destructor - */ - ~Tau2HNLFlux(); - - bool MakeFlux(const simb::MCFlux &flux, MeVPrtlFlux &hnl, double &weight) override; - void configure(const fhicl::ParameterSet&) override; - - double MaxWeight() override; - -private: - // config - double fM; //!< Mass of HNL [GeV] - double fMagUt4; -}; - -Tau2HNLFlux::Tau2HNLFlux(fhicl::ParameterSet const &pset): - IMeVPrtlStage("Tau2HNLFlux"), - IMeVPrtlFlux(pset) -{ - this->configure(pset); - -} - -//------------------------------------------------------------------------------------------------------------------------------------------ - -Tau2HNLFlux::~Tau2HNLFlux() -{ -} - -// helper functions -// -// tau -> pi + HNL -double hnl_momentum(double tau_mass, double pion_mass, double hnl_mass) { - if (tau_mass - pion_mass < hnl_mass) return -1.; - - return sqrt(tau_mass * tau_mass * tau_mass * tau_mass - -2 * tau_mass * tau_mass * pion_mass * pion_mass - -2 * tau_mass * tau_mass * hnl_mass * hnl_mass - + pion_mass * pion_mass * pion_mass * pion_mass - + hnl_mass * hnl_mass * hnl_mass * hnl_mass - -2 * pion_mass * pion_mass * hnl_mass * hnl_mass) / ( 2 * tau_mass ); -} - -/* Polarization of a HNL emerging from a two body meson decay (M-> l N) - m_l is the mass of the lepton and m_M the mass of the parent meson - See arXiv:2109.10358 for more details. - Due to crossing symmetry the polarization of the tau -> m N gives the same result */ -double PolHNL(double m_HNL, double m_l, double m_M) -{ - double yl = m_l / m_M; - double yHNL = m_HNL / m_M; - double numterm = (yl*yl - yHNL * yHNL) * sqrt(pow(yHNL,4) + (1.0 - yl * yl)*(1.0 - yl * yl) - 2.0 * yHNL * yHNL * (1.0 + yl * yl)); - double denterm = pow(yl,4) + pow(yHNL,4) - 2.0 * yl * yl * yHNL * yHNL - yl * yl - yHNL * yHNL; - return numterm / denterm; -} - -double BranchingRatio(double hnl_mass, double u4) { - double Gfermi = Constants::Instance().Gfermi; - double Vud2 = Constants::Instance().abs_Vud_squared; - double fpion = Constants::Instance().fpion; - double tau_mass = Constants::Instance().tau_mass; - double tau_lifetime = Constants::Instance().tau_lifetime; - double pi_mass = Constants::Instance().piplus_mass; - double hbar = Constants::Instance().hbar; - - double coupling = 0.9*tau_lifetime*u4*Gfermi*Gfermi*Vud2*fpion*fpion*tau_mass*tau_mass*tau_mass / (16*M_PI) / hbar; - - double hnl_mass2 = hnl_mass*hnl_mass; - double tau_mass2 = tau_mass*tau_mass; - double pi_mass2 = pi_mass*pi_mass; - - double kinematic_factor = \ - ((1 - hnl_mass2 / tau_mass2) * (1 - hnl_mass2 / tau_mass2) \ - - (pi_mass2 / tau_mass2) * (1 + hnl_mass2 / tau_mass2)) \ - *sqrt((1 - (pi_mass - hnl_mass)*(pi_mass - hnl_mass)/tau_mass2)*(1 - (hnl_mass+pi_mass)*(hnl_mass+pi_mass)/tau_mass2)); - - return coupling * kinematic_factor; -} - -//------------------------------------------------------------------------------------------------------------------------------------------ -void Tau2HNLFlux::configure(fhicl::ParameterSet const &pset) -{ - fM = pset.get("M"); - fMagUt4 = pset.get("MagUt4"); - - double max_mass = Constants::Instance().tau_mass - Constants::Instance().piplus_mass; - - if (fM > max_mass) { - throw cet::exception("Tau2HNLFlux Tool: BAD MASS. Configured mass (" + std::to_string(fM) + - ") is larger than maximum allowed by enabled couplings (" + std::to_string(max_mass) + ")."); - } - -} - -double Tau2HNLFlux::MaxWeight() { - return BranchingRatio(fM, fMagUt4); -} - -bool Tau2HNLFlux::MakeFlux(const simb::MCFlux &flux, evgen::ldm::MeVPrtlFlux &hnl, double &weight) { - // make the tau parent - evgen::ldm::MesonParent tau(flux); - if (abs(tau.meson_pdg) != 15) return false; // Only take taus - - TLorentzVector Beam4 = BeamOrigin(); - - // get position in detector frame - hnl.pos_beamcoord = tau.pos; - hnl.pos = tau.pos; - hnl.pos.Transform(fBeam2Det); - hnl.pos += Beam4; - - double br = BranchingRatio(fM, fMagUt4); - - std::cout << "BR: " << br << std::endl; - - // ignore if we can't make this hnl - // Ignore if branching ratio is exactly 0. - if (br == 0.) return false; - - // get the momentum direction in the tau parent rest frame - double p = hnl_momentum(Constants::Instance().tau_mass, Constants::Instance().piplus_mass, fM); - double e = sqrt(p*p + fM * fM); - // Two-body decays are isotropic - hnl.mom = TLorentzVector(p*RandomUnitVector(), e); - - // boost to lab frame - TLorentzVector mom = hnl.mom; - mom.Boost(tau.mom.BoostVector()); - - hnl.mom_beamcoord = mom; - // rotate to detector frame - hnl.mom = mom; - hnl.mom.Transform(fBeam2Det); - - hnl.mmom_beamcoord = tau.mom; - // also save the tau momentum in the detector frame - hnl.mmom = tau.mom; - hnl.mmom.Transform(fBeam2Det); - - // and save the secondary momentum - hnl.sec = hnl.mmom - hnl.mom; - hnl.sec_beamcoord = hnl.mmom_beamcoord - hnl.mom_beamcoord; - - // The weight is the importance weight times the branching-ratio weight - weight = tau.weight * br; - - // set the mixing - hnl.C1 = 0.; - hnl.C2 = 0.; - hnl.C3 = fMagUt4; - hnl.mass = fM; - - hnl.meson_pdg = tau.meson_pdg; - hnl.secondary_pdg = 211 * (tau.meson_pdg > 0 ? 1 : -1); - hnl.generator = 1; // kHNL - - // equivalent neutrino energy -- doesn't apply here - hnl.equiv_enu = -1; - - -// Get the HNL Polarization - double meson_mass = Constants::Instance().kplus_mass; - if(abs(hnl.meson_pdg) == 321) { - meson_mass = Constants::Instance().kplus_mass; - }else if(abs(hnl.meson_pdg) == 211) { - meson_mass = Constants::Instance().piplus_mass; - } - - - hnl.polarization = PolHNL(fM , Constants::Instance().tau_mass, meson_mass); - - return true; -} - -DEFINE_ART_CLASS_TOOL(Tau2HNLFlux) - -} // namespace ldm -} // namespace evgen diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/PiZero2DPFlux_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/PiZero2DPFlux_tool.cc deleted file mode 100644 index e8d2224f2..000000000 --- a/sbncode/EventGenerator/MeVPrtl/Tools/DP/old/PiZero2DPFlux_tool.cc +++ /dev/null @@ -1,275 +0,0 @@ -/** - * - */ - -// Framework Includes -#include "art/Framework/Core/EDProducer.h" -#include "art/Framework/Principal/Event.h" -#include "art/Framework/Principal/Handle.h" -#include "art/Framework/Services/Registry/ServiceHandle.h" -#include "art/Persistency/Common/PtrMaker.h" -#include "art/Utilities/ToolMacros.h" -#include "cetlib/cpu_timer.h" -#include "fhiclcpp/ParameterSet.h" -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "CLHEP/Random/RandFlat.h" - -// local includes -#include "sbncode/EventGenerator/MeVPrtl/Tools/IMeVPrtlFlux.h" -#include "sbncode/EventGenerator/MeVPrtl/Tools/Constants.h" - -#include "sbnobj/Common/EventGen/MeVPrtl/MeVPrtlFlux.h" -#include "sbnobj/Common/EventGen/MeVPrtl/MesonParent.h" - -// ROOT -#include "TVector3.h" - -// std includes -#include -#include -#include - -#include "TDatabasePDG.h" - -//------------------------------------------------------------------------------------------------------------------------------------------ -// implementation follows - -namespace evgen { -namespace ldm { -/** - * @brief PiZero2DPFlux class definiton - * - * Implementation of Kaon->DP branching ratio taken from: - * arXiv:1912.07622 - */ -class PiZero2DPFlux : public IMeVPrtlFlux -{ -public: - /** - * @brief Constructor - */ - PiZero2DPFlux(fhicl::ParameterSet const &pset); - - /** - * @brief Destructor - */ - ~PiZero2DPFlux(); - - bool MakeFlux(const simb::MCFlux &flux, MeVPrtlFlux &dp, double &weight) override; - void configure(const fhicl::ParameterSet&) override; - - double MaxWeight() override; - -private: - // config - double fM; //!< Mass of DP [GeV] - double fe; - double fTarget2Absorber; - double Pi0ToDPBR(double mA) const; -}; - -PiZero2DPFlux::PiZero2DPFlux(fhicl::ParameterSet const &pset): - IMeVPrtlStage("PiZero2DPFlux"), - IMeVPrtlFlux(pset) -{ - this->configure(pset); - -} - -//------------------------------------------------------------------------------------------------------------------------------------------ - -PiZero2DPFlux::~PiZero2DPFlux() -{ -} - -// helper functions -// -// pi0 -> photon + DP -double dp_momentum(double pi0_mass, double gamma_mass, double dp_mass) { - if (pi0_mass - gamma_mass < dp_mass) return -1.; - - return sqrt(pi0_mass * pi0_mass * pi0_mass * pi0_mass - -2 * pi0_mass * pi0_mass * gamma_mass * gamma_mass - -2 * pi0_mass * pi0_mass * dp_mass * dp_mass - + gamma_mass * gamma_mass * gamma_mass * gamma_mass - + dp_mass * dp_mass * dp_mass * dp_mass - -2 * gamma_mass * gamma_mass * dp_mass * dp_mass) / ( 2 * pi0_mass ); -} - - -double SMKaonBR(int pi0_pdg) { - // The Kaons in Dk2nu file only include those that decay to neutrinos. - // - // We want all kaons -- in order to account for this, we divide by the - // branching-ratio of kaons to neutrinos - // - // Taken from: - // /cvmfs/minerva.opensciencegrid.org/minerva/beamsim/x86_64/geant4/source/particles/hadrons/mesons/src/G4KaonPlus.cc - // /cvmfs/minerva.opensciencegrid.org/minerva/beamsim/x86_64/geant4/source/particles/hadrons/mesons/src/G4KaonZerLong.cc - switch (pi0_pdg) { - case 321: - return 0.6339 /* 5 */ + 0.0559 /* 6 */ + 0.0330 /* 7 */; - case -321: - return 0.6339 /* 8 */ + 0.0559 /* 9 */ + 0.0330 /* 10 */; - case 130: - return 0.2020 /* 1 */ + 0.2020 /* 2 */ + 0.1348 /* 3 */ + 0.1348 /* 4 */; - default: - return -1; - } -} - -double BranchingRatio(double dp_mass, double u4, bool is_muon) { - double lep_mass = is_muon ? Constants::Instance().muon_mass : Constants::Instance().elec_mass; - double kplus_mass = Constants::Instance().kplus_mass; - - if (dp_mass > kplus_mass - lep_mass) return 0.; - - double smbr = is_muon ? Constants::Instance().kaonp_mup_numu : Constants::Instance().kaonp_ep_nue; - double lep_ratio = (lep_mass * lep_mass) / (kplus_mass * kplus_mass); - double dp_ratio = (dp_mass * dp_mass) / (kplus_mass * kplus_mass); - double kinematic_factor = (lep_ratio + dp_ratio - (lep_ratio - dp_ratio) * (lep_ratio - dp_ratio)) \ - * sqrt(1 + dp_ratio * dp_ratio + lep_ratio * lep_ratio - 2*(dp_ratio + lep_ratio + dp_ratio*lep_ratio)) \ - / (lep_ratio * (1. - lep_ratio) * (1. - lep_ratio)); - - // scale the branching ratio - return smbr * (u4 / (1. - u4)) * kinematic_factor; -} - -std::pair Branch(double dp_mass, double ue4, double um4, double rand) { - double kplus_mass = Constants::Instance().kplus_mass; - - double br_muon = (um4 > 0. && dp_mass < kplus_mass - Constants::Instance().muon_mass) ? BranchingRatio(dp_mass, um4, true) : 0.; - double br_elec = (ue4 > 0. && dp_mass < kplus_mass - Constants::Instance().elec_mass) ? BranchingRatio(dp_mass, ue4, false): 0.; - if (br_muon == 0. && br_elec == 0.) return {0., false}; - - double br_weight = br_muon + br_elec; - - bool is_muon = rand < (br_muon / br_weight); - - return {br_weight, is_muon}; -} - - double PiZero2DPFlux::Pi0ToDPBR(double mA) const { - - double mpi0 = Constants::Instance().pizero_mass; - double br_gammagamma = 0.988; // PDG value - - if (mA >= mpi0) return 0.0; - - double factor = 1.0 - (mA * mA) / (mpi0 * mpi0); - return 2.0 * fe * fe * std::pow(factor, 3) * br_gammagamma; - } - -//------------------------------------------------------------------------------------------------------------------------------------------ -void PiZero2DPFlux::configure(fhicl::ParameterSet const &pset) -{ - fM = pset.get("M"); - fe = pset.get("e"); - // fMagUm4 = pset.get("MagUm4"); - // fMagUe4 = pset.get("MagUe4"); - - fTarget2Absorber = pset.get("Target2Absorber", 5000); - // fKDAROnly = pset.get("KDAROnly", false); - /* - double max_mass = (fMagUe4 > 0.) ? (Constants::Instance().kplus_mass - Constants::Instance().elec_mass) : - (Constants::Instance().kplus_mass - Constants::Instance().muon_mass); - - if (fM > max_mass) { - throw cet::exception("PiZero2DPFlux Tool: BAD MASS. Configured mass (" + std::to_string(fM) + - ") is larger than maximum allowed by enabled couplings (" + std::to_string(max_mass) + ")."); - } - */ -} - -double PiZero2DPFlux::MaxWeight() { - // Weight comes from the NuMi importance weight -- max is 100 (add in an epsilon) - // Scale by the branching ratios here - // return 100.0001 * std::max(BranchingRatio(fM, fMagUe4, false) / SMKaonBR(321), BranchingRatio(fM, fMagUm4, true) / SMKaonBR(321)); - return 1; -} - -bool PiZero2DPFlux::MakeFlux(const simb::MCFlux &flux, evgen::ldm::MeVPrtlFlux &dp, double &weight) { - // make the pi0 parent - evgen::ldm::MesonParent kaon(flux); - if (abs(kaon.meson_pdg) != 111) return false; // Only take charged kaons - double mpi0 = Constants::Instance().pizero_mass; - TLorentzVector Beam4 = BeamOrigin(); - - // get position in detector frame - dp.pos_beamcoord = kaon.pos; - dp.pos = kaon.pos; - dp.pos.Transform(fBeam2Det); - dp.pos += Beam4; - - // Branch the parent Kaon Decay - double dp_mass = fM; - // std::pair decay = Branch(dp_mass, fMagUe4, fMagUm4, GetRandom()); - //double br = decay.first; - - double br = Pi0ToDPBR(fM); - - //bool is_muon = decay.second; - //double lep_mass = is_muon ? Constants::Instance().muon_mass : Constants::Instance().elec_mass; - if (br == 0.) return false; - if (fVerbose) std::cout << "BR: " << br << std::endl; - - // get the momentum direction in the kaon parent rest frame - double p = (mpi0 * mpi0 - fM * fM) / (2.0 * mpi0); - double e = sqrt(p*p + dp_mass * dp_mass); - // Two-body decays are isotropic - dp.mom = TLorentzVector(p*RandomUnitVector(), e); - - // boost to lab frame - TLorentzVector mom = dp.mom; - mom.Boost(kaon.mom.BoostVector()); - - dp.mom_beamcoord = mom; - // rotate to detector frame - dp.mom = mom; - dp.mom.Transform(fBeam2Det); - - dp.mmom_beamcoord = kaon.mom; - // also save the kaon momentum in the detector frame - dp.mmom = kaon.mom; - dp.mmom.Transform(fBeam2Det); - - // and save the secondary momentum - dp.sec = dp.mmom - dp.mom; - dp.sec_beamcoord = dp.mmom_beamcoord - dp.mom_beamcoord; - - // The weight is the importance weight times the branching-ratio weight - weight = kaon.weight * br / SMKaonBR(kaon.meson_pdg); - - // set the mixing - dp.C1 = fe; - dp.C2 = 0; - dp.C3 = 0.; - dp.mass = fM; - - dp.meson_pdg = kaon.meson_pdg; - dp.secondary_pdg = 22; - dp.generator = 2; // kDP - - // equivalent neutrino energy - dp.equiv_enu = EnuLab(flux.fnecm, dp.mmom, dp.pos); - - - /* // Get the DP Polarization - double meson_mass = Constants::Instance().kplus_mass; - if(abs(dp.meson_pdg) == 321) { - meson_mass = Constants::Instance().kplus_mass; - }else if(abs(dp.meson_pdg) == 211) { - meson_mass = Constants::Instance().piplus_mass; - } - */ - // dp.polarization = PolDP(fM , lep_mass, meson_mass); - //Account for the Polarization of m+ ->l+N being opposite to the polarization of m- -> l-bar{N} due to CP - // if(dp.secondary_pdg < 0) dp.polarization *= -1; - - return true; -} - -DEFINE_ART_CLASS_TOOL(PiZero2DPFlux) - -} // namespace ldm -} // namespace evgen From 4b041695df038483b018dfca537a58dfef49af9d Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Wed, 29 Apr 2026 15:21:44 +0200 Subject: [PATCH 09/14] Delete sbncode/EventGenerator/MeVPrtl/Tools/BNBKaonGenDK2NU_tool.cc Not intended to be part of branch --- .../MeVPrtl/Tools/BNBKaonGenDK2NU_tool.cc | 1257 ----------------- 1 file changed, 1257 deletions(-) delete mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/BNBKaonGenDK2NU_tool.cc diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/BNBKaonGenDK2NU_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/BNBKaonGenDK2NU_tool.cc deleted file mode 100644 index 25b1dbed4..000000000 --- a/sbncode/EventGenerator/MeVPrtl/Tools/BNBKaonGenDK2NU_tool.cc +++ /dev/null @@ -1,1257 +0,0 @@ -// /** -// * -// */ - -// // Framework Includes -// #include "art/Framework/Core/EDProducer.h" -// #include "art/Framework/Principal/Event.h" -// #include "art/Framework/Principal/Handle.h" -// #include "art/Framework/Services/Registry/ServiceHandle.h" -// #include "art/Persistency/Common/PtrMaker.h" -// #include "art/Utilities/ToolMacros.h" -// #include "cetlib/cpu_timer.h" -// #include "fhiclcpp/ParameterSet.h" -// #include "messagefacility/MessageLogger/MessageLogger.h" -// #include "CLHEP/Random/RandFlat.h" -// #include "ifdh_art/IFDHService/IFDH_service.h" - -// #include "nusimdata/SimulationBase/MCFlux.h" - -// // local includes -// #include "IMesonGen.h" -// #include "boone.h" -// #include "PDGCodes.h" - -// // LArSoft includes -// #include "dk2nu/tree/dk2nu.h" -// #include "dk2nu/tree/dkmeta.h" -// #include "dk2nu/tree/NuChoice.h" - -// // ROOT -// #include "TVector3.h" -// #include "TTree.h" -// #include "TFile.h" -// #include "TTreeReader.h" -// #include "TTreeReaderValue.h" - -// // std includes -// #include -// #include -// #include - -// //------------------------------------------------------------------------------------------------------------------------------------------ -// // implementation follows - -// namespace evgen { -// namespace ldm { -// /** -// * @brief BNBKaonGen class definiton -// */ -// class BNBKaonGen : public IMesonGen -// { -// public: -// /** -// * @brief Constructor -// */ -// BNBKaonGen(fhicl::ParameterSet const &pset); - -// /** -// * @brief Destructor -// */ -// ~BNBKaonGen(); - -// double GetPOT() override; -// simb::MCFlux GetNext() override; - -// void configure(const fhicl::ParameterSet&) override; - -// const bsim::Dk2Nu *GetNextEntry(); -// const bsim::BooNe *GetNextEntry(); -// std::vector LoadFluxFiles(); -// simb::MCFlux MakeMCFlux(const bsim::Dk2Nu &dk2nu); -// simb::MCFlux MakeMCFlux(const bsim::BooNe &boone); -// double LoadPOT(); - -// // no weights -// double MaxWeight() override { return -1.; } - -// private: -// // config -// std::string fSearchPath; -// std::vector fSearchPatterns; -// unsigned long fMaxFluxFileMB; -// std::string fFluxCopyMethod; -// bool fRandomizeFiles; -// bool fVerbose; - -// std::string fTreeName; -// std::string fMetaTreeName; - -// // info for tracking files -// unsigned fFileIndex; -// bool fNewFile; -// std::vector fFluxFiles; - -// // info for tracking entry in file -// unsigned fEntry; -// unsigned fEntryStart; - -// // ROOT Holders -// TTree *fFluxTree; -// TFile *fFluxFile; -// bsim::Dk2Nu *fDk2Nu; -// bsim::BooNe *fBooNe; - -// // count POT -// double fAccumulatedPOT; -// double fThisFilePOT; - -// }; - -// BNBKaonGen::BNBKaonGen(fhicl::ParameterSet const &pset): -// IMeVPrtlStage("BNBKaonGen") -// { -// configure(pset); - -// // copy the flux files locally -// fFluxFiles = LoadFluxFiles(); - -// // setup indices -// fFileIndex = 0; -// fEntry = 0; -// fEntryStart = 0; -// fNewFile = true; -// fFluxTree = NULL; -// fFluxFile = NULL; -// fDk2Nu = new bsim::Dk2Nu; -// fBooNe = new bsim::BooNe; - -// fAccumulatedPOT = 0.; -// fThisFilePOT = 0.; - -// } - -// //------------------------------------------------------------------------------------------------------------------------------------------ - -// BNBKaonGen::~BNBKaonGen() -// { - -// if (fDk2Nu) delete fDk2Nu; -// if (fBooNe) delete fBooNe; -// } - -// //------------------------------------------------------------------------------------------------------------------------------------------ -// void BNBKaonGen::configure(fhicl::ParameterSet const &pset) -// { -// fSearchPath = pset.get("SearchPath"); -// fSearchPatterns = pset.get>("FluxFiles"); -// fMaxFluxFileMB = pset.get("MaxFluxFileMB", 2 * 1024); -// fFluxCopyMethod = pset.get("FluxCopyMethod", "IFDH"); -// fTreeName = pset.get("TreeName"); -// fMetaTreeName = pset.get("MetaTreeName"); -// fRandomizeFiles = pset.get("RandomizeFiles"); -// fVerbose = pset.get("Verbose", true); -// fFluxMode = pset.get("FluxMode", "G4BNB"); -// if (fFluxMode != "BooNE" && fFluxMode != "Dk2Nu") { -// throw cet::exception("BNBKaonGen") -// << "Invalid FluxMode = " << fFluxMode -// << " (allowed: BooNE, Dk2Nu)"; -// } - - -// if(fVerbose){ -// std::cout << "Searching for flux files at path: " << fSearchPath << std::endl; -// std::cout << "With patterns:\n"; -// for (const std::string &s: fSearchPatterns) std::cout << s << std::endl; -// std::cout << "With copy method: " << fFluxCopyMethod << std::endl; -// } - -// } - -// std::vector BNBKaonGen::LoadFluxFiles() { -// art::ServiceHandle ifdhp; - -// std::vector> allFiles; - -// // find the flux files -// for (unsigned i = 0; i < fSearchPatterns.size(); i++) { -// std::vector> thisList = ifdhp->findMatchingFiles(fSearchPath, fSearchPatterns[i]); -// std::copy (thisList.begin(), thisList.end(), std::back_inserter(allFiles)); -// } - -// // first randomize the flux files -// std::vector order(allFiles.size(), 0); -// if (fRandomizeFiles) { -// std::vector rand(allFiles.size(), 0.); -// CLHEP::RandFlat::shootArray(fEngine, rand.size(), &rand[0]); -// TMath::Sort(allFiles.size(), &rand[0], &order[0], false); -// } -// else { -// for (unsigned i = 0; i < order.size(); i++) { -// order[i] = i; -// } -// } - -// // If we are directly accessing the files, no need to copy -// if (fFluxCopyMethod == "DIRECT") { -// if(fVerbose) std::cout << "DIRECTLY ACCESSING FLUX FILES.\n"; -// std::vector files(allFiles.size()); -// for (unsigned i = 0; i < order.size(); i++) { -// files[i] = allFiles[order[i]].first; -// } -// return files; -// } - -// // copy over up to the provided limit -// std::vector> selected; -// unsigned long totalBytes = 0; -// unsigned ind = 0; -// while (totalBytes < (fMaxFluxFileMB * 1024 * 1024) && ind < allFiles.size()) { -// selected.push_back(allFiles[order[ind]]); -// totalBytes += allFiles[order[ind]].second; -// ind ++; -// } - -// // copy the files locally -// std::vector> localFiles = ifdhp->fetchSharedFiles(selected, fFluxCopyMethod); - -// std::vector files(localFiles.size()); -// for (unsigned i = 0; i < localFiles.size(); i++) { -// files[i] = localFiles[i].first; -// } - -// return files; -// } - -// double BNBKaonGen::LoadPOT() { -// TTreeReader metaReader(fMetaTreeName.c_str(), fFluxFile); -// TTreeReaderValue pot(metaReader, "pots"); - -// double total_pot = 0.; - -// while (metaReader.Next()) { -// total_pot += *pot; -// } - -// return total_pot; -// } - - -// double BNBKaonGen::GetPOT() { -// double ret = fAccumulatedPOT; -// fAccumulatedPOT = 0.; -// return ret; -// } - -// const bsim::BooNe *BNBKaonGen::GetNextEntry() { -// // new file -- set the start entry -// if (fNewFile) { -// // wrap file index around -// if (fFileIndex >= fFluxFiles.size()) { -// fFileIndex = 0; -// } -// // if (fFileIndex >= fFluxFiles.size()) { -// // throw cet::exception("FluxReader Out of Files", -// // "At file index (" + std::to_string(fFileIndex) + ") of available files (" + std::to_string(fFluxFiles.size()) + ")."); -// // } - -// if(fVerbose) std::cout << "New file: " << fFluxFiles[fFileIndex] << " at index: " << fFileIndex << " of: " << fFluxFiles.size() << std::endl; -// if (fFluxFile) delete fFluxFile; -// fFluxFile = new TFile(fFluxFiles[fFileIndex].c_str()); -// fFluxTree = (TTree*)fFluxFile->Get(fTreeName.c_str()); -// // fFluxTree->SetBranchAddress("dk2nu",&fDk2Nu); -// fBooNe = new bsim::BooNe(fFluxFiles[fFileIndex].c_str()); - -// // Start at a random index in this file -// fEntryStart = CLHEP::RandFlat::shootInt(fEngine, fFluxTree->GetEntries()-1); -// fEntry = fEntryStart; - -// // load the POT in this file -// // fThisFilePOT = LoadPOT(); -// fNewFile = false; -// } -// else { -// fEntry = (fEntry + 1) % fFluxTree->GetEntries(); -// // if this is the last entry, get ready for the next file -// if ((fEntry + 1) % fFluxTree->GetEntries() == fEntryStart) { -// fFileIndex ++; -// fNewFile = true; -// } -// } - -// // count the POT -// fBooNe->myNtuple.run = fEntry; -// fBooNe->myNtuple.eventn = fFileIndex; - -// fAccumulatedPOT += fBooNe->GetPOT(); - -// fFluxTree->GetEntry(fEntry); -// fBooNe->GetEntry(fEntry); -// return fBooNe; -// } - -// const bsim::Dk2Nu *BNBKaonGen::GetNextEntry() { -// // new file -- set the start entry -// if (fNewFile) { -// // wrap file index around -// if (fFileIndex >= fFluxFiles.size()) { -// fFileIndex = 0; -// } -// // if (fFileIndex >= fFluxFiles.size()) { -// // throw cet::exception("FluxReader Out of Files", -// // "At file index (" + std::to_string(fFileIndex) + ") of available files (" + std::to_string(fFluxFiles.size()) + ")."); -// // } - -// std::cout << "New file: " << fFluxFiles[fFileIndex] << " at index: " << fFileIndex << " of: " << fFluxFiles.size() << std::endl; -// if (fFluxFile) delete fFluxFile; -// fFluxFile = new TFile(fFluxFiles[fFileIndex].c_str()); -// fFluxTree = (TTree*)fFluxFile->Get(fTreeName.c_str()); -// fFluxTree->SetBranchAddress("dk2nu",&fDk2Nu); - -// // Start at a random index in this file -// fEntryStart = CLHEP::RandFlat::shootInt(fEngine, fFluxTree->GetEntries()-1); -// fEntry = fEntryStart; - -// // load the POT in this file -// fThisFilePOT = LoadPOT(); -// fNewFile = false; -// } -// else { -// fEntry = (fEntry + 1) % fFluxTree->GetEntries(); -// // if this is the last entry, get ready for the next file -// if ((fEntry + 1) % fFluxTree->GetEntries() == fEntryStart) { -// fFileIndex ++; -// fNewFile = true; -// } -// } - -// // count the POT -// fAccumulatedPOT += fThisFilePOT / fFluxTree->GetEntries(); - -// fFluxTree->GetEntry(fEntry); -// return fDk2Nu; -// } - -// simb::MCFlux BNBKaonGen::GetNext() { -// if (fFluxMode == "G4BNB") { -// mf::LogWarning("BNBKaonGen") << "BNBKaonGen is set to G4BNB mode, but this tool only supports BooNE mode. Switching to BooNE mode."; -// const bsim::Dk2Nu *flux = GetNextEntry(); -// } -// else{ -// const bsim::BooNe *flux = GetNextEntry(); -// } -// return MakeMCFlux(*flux); -// } - -// simb::MCFlux BNBKaonGen::MakeMCFlux(const bsim::BooNe &boone) { - -// simb::MCFlux flux; -// auto fBooneNtp=boone.myNtuple; - -// if ( fBooneNtp.ntp == 1 ) { -// flux.fntype = 12; //nue -// } -// else if ( fBooneNtp.ntp == 2 ) { -// flux.fntype = -12; //nuebar -// } -// else if ( fBooneNtp.ntp == 3 ) { -// flux.fntype = 14; //numu -// } -// else if ( fBooneNtp.ntp == 4 ) { -// flux.fntype = -14; //numubar -// } -// else{ -// mf::LogWarning("BooNEInterface") << "Neutrino type not recognized! ntp = " << fBooneNtp.ntp -// << std::endl; -// } - -// flux.fFluxType = simb::kDk2Nu; -// flux.fnimpwt = fBooneNtp.beamwgt; -// flux.fvx = fBooneNtp.ini_pos[0][0]; //0 -// flux.fvy = fBooneNtp.ini_pos[0][1]; //0 -// flux.fvz = fBooneNtp.ini_pos[0][2]; //0 -// flux.fpdpx = fBooneNtp.fin_mom[1][0]; //1 final -// flux.fpdpy = fBooneNtp.fin_mom[1][1]; //1 final -// flux.fpdpz = fBooneNtp.fin_mom[1][2]; //1 final -// flux.fpppz = fBooneNtp.ini_mom[1][2]; //1 init - -// // Momentum projected in dx/dz or dy/dz -// flux.fpppz = fBooneNtp.ini_mom[1][2]; //1 init -// double pppx = fBooneNtp.ini_mom[1][0]; //1 init -// double pppy = fBooneNtp.ini_mom[1][1]; //1 init -// double apppz = flux.fpppz; -// if (TMath::Abs(flux.fpppz) < 1.0e-30) apppz = 1.0e-30; -// flux.fppdxdz = pppx / apppz; -// flux.fppdydz = pppy / apppz; - -// flux.fppmedium = 0.; -// flux.fppenergy = fBooneNtp.ini_eng[1]; - -// int npart = fBooneNtp.npart; -// int ptype_input = fBooneNtp.id[1]; -// int tptype_input = fBooneNtp.id[npart-2]; - -// if (ptype_input != 0) ptype_input = evgen::GeantToPdg(ptype_input); -// if (tptype_input != 0) tptype_input= evgen::GeantToPdg(tptype_input); - -// flux.fptype = ptype_input; -// flux.ftptype = tptype_input; - -// ///// -// // Now need to calculate ndecay -// ///// - -// double Nenergy = fBooneNtp.ini_eng[0]; -// double Ndxdz = fBooneNtp.ini_mom[0][0] / fBooneNtp.ini_mom[0][2]; -// double Ndydz = fBooneNtp.ini_mom[0][1] / fBooneNtp.ini_mom[0][2]; - -// double ppenergy = fBooneNtp.ini_eng[1]; -// double pdPx = fBooneNtp.fin_mom[1][0]; -// double pdPy = fBooneNtp.fin_mom[1][1]; -// double pdPz = fBooneNtp.fin_mom[1][2]; - -// double ppdxdz = fBooneNtp.ini_mom[1][0] / fBooneNtp.ini_mom[1][2]; -// double ppdydz = fBooneNtp.ini_mom[1][1] / fBooneNtp.ini_mom[1][2]; -// double pppz = fBooneNtp.ini_mom[1][2]; - -// // Get the neutrino energy in the parent decay cm -// double parent_mass = std::sqrt(ppenergy * ppenergy - -// pppz * pppz * (ppdxdz * ppdxdz + -// ppdydz * ppdydz + -// 1.)); - -// double parent_energy = std::sqrt(pdPx * pdPx + -// pdPy * pdPy + -// pdPz * pdPz + -// parent_mass * parent_mass); - -// double gamma = parent_energy / parent_mass; -// double beta[3]; -// beta[0] = pdPx / parent_energy; -// beta[1] = pdPy / parent_energy; -// beta[2] = pdPz / parent_energy; - -// double partial = fBooneNtp.ini_mom[0][2] * gamma * -// (beta[0] * Ndxdz + -// beta[1] * Ndydz + -// beta[2]); - -// double Necm = gamma * Nenergy - partial; - -// if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 1) flux.fndecay = 1; -// else if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 2) flux.fndecay = 2; -// else if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 3) flux.fndecay = 3; -// else if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 4) flux.fndecay = 4; -// else if (fBooneNtp.id[1] == 11 && fBooneNtp.ntp == 3) { -// //check if it is a two or three body decay -// if (fabs((parent_mass*parent_mass-0.105658389*0.105658389)/(2.*parent_mass)-Necm)/Necm <= 0.001) -// //two body decay (numu + mu+) -// flux.fndecay = 5; -// else { -// //three body decay (numu + pi0 + mu+) -// flux.fndecay = 7; -// } -// } -// else if (fBooneNtp.id[1] == 11 && fBooneNtp.ntp == 1) flux.fndecay = 6; -// else if (fBooneNtp.id[1] == 12 && fBooneNtp.ntp == 4) { -// if (fabs((parent_mass*parent_mass-0.105658389*0.105658389)/(2.*parent_mass)-Necm)/Necm <= 0.001) { -// //two body decay (numu + mu+) -// flux.fndecay = 8; -// } -// else { -// //three body decay (numu + pi0 + mu+) -// flux.fndecay = 10; -// } -// } -// else if (fBooneNtp.id[1] == 12 && fBooneNtp.ntp == 2) flux.fndecay = 9; -// else if (fBooneNtp.id[1] == 5 ) flux.fndecay = 11; -// else if (fBooneNtp.id[1] == 6 ) flux.fndecay = 12; -// else if (fBooneNtp.id[1] == 8 ) flux.fndecay = 13; -// else if (fBooneNtp.id[1] == 9 ) flux.fndecay = 14; - -// ///// -// // End calculation of ndecay -// ///// -// double mupare; -// double muparpx; -// double muparpy; -// double muparpz; - -// if ( fBooneNtp.id[1] == 5 || fBooneNtp.id[1] == 6) { -// mupare = fBooneNtp.ini_eng[2]; -// muparpx = fBooneNtp.fin_mom[2][0]; -// muparpy = fBooneNtp.fin_mom[2][1]; -// muparpz = fBooneNtp.fin_mom[2][2]; -// } else { -// mupare = -9999.; -// muparpx = -9999.; -// muparpy = -9999.; -// muparpz = -9999.; -// } - -// flux.fmuparpx = muparpx; -// flux.fmuparpy = muparpy; -// flux.fmuparpz = muparpz; -// flux.fmupare = mupare; - -// flux.fnecm = Necm; - -// flux.fppvx = fBooneNtp.ini_pos[1][0]; -// flux.fppvy = fBooneNtp.ini_pos[1][1]; -// flux.fppvz = fBooneNtp.ini_pos[1][2]; - -// flux.ftvx = fBooneNtp.ini_pos[npart-2][0]; -// flux.ftvy = fBooneNtp.ini_pos[npart-2][1]; -// flux.ftvz = fBooneNtp.ini_pos[npart-2][2]; -// flux.ftpx = fBooneNtp.ini_mom[npart-2][0]; -// flux.ftpy = fBooneNtp.ini_mom[npart-2][1]; -// flux.ftpz = fBooneNtp.ini_mom[npart-2][2]; -// // flux.ftgen = dk2nu.tgtexit.tgen; - -// flux.frun = fBooneNtp.run; -// flux.fevtno = fBooneNtp.eventn; -// flux.ftgptype = evgen::GeantToPdg(fBooneNtp.id[npart-2]); - -// // flux.fnenergyn = flux.fnenergyf = enu; -// // flux.fnwtnear = flux.fnwtfar = wgt; -// // ignore variables dealing with the neutrino -// flux.fnenergyn = -1; -// flux.fnwtnear = flux.fnwtfar = -1; -// flux.fdk2gen = -1; - -// // // placeholder for time -// flux.fxpoint = fBooneNtp.ini_t[0]; - -// return flux; -// } - -// simb::MCFlux BNBKaonGen::MakeMCFlux(const bsim::Dk2Nu &dk2nu) { -// simb::MCFlux flux; - -// flux.fFluxType = simb::kDk2Nu; -// flux.fntype = dk2nu.decay.ntype; -// flux.fnimpwt = dk2nu.decay.nimpwt; -// flux.fvx = dk2nu.decay.vx; -// flux.fvy = dk2nu.decay.vy; -// flux.fvz = dk2nu.decay.vz; -// flux.fpdpx = dk2nu.decay.pdpx; -// flux.fpdpy = dk2nu.decay.pdpy; -// flux.fpdpz = dk2nu.decay.pdpz; -// flux.fppdxdz = dk2nu.decay.ppdxdz; -// flux.fppdydz = dk2nu.decay.ppdydz; -// flux.fpppz = dk2nu.decay.pppz; -// flux.fppenergy = dk2nu.decay.ppenergy; -// flux.fppmedium = dk2nu.decay.ppmedium; -// flux.fptype = dk2nu.decay.ptype; -// flux.fndecay = dk2nu.decay.ndecay; -// flux.fmuparpx = dk2nu.decay.muparpx; -// flux.fmuparpy = dk2nu.decay.muparpy; -// flux.fmuparpz = dk2nu.decay.muparpz; -// flux.fmupare = dk2nu.decay.mupare; -// flux.fnecm = dk2nu.decay.necm; - -// flux.fppvx = dk2nu.ppvx; -// flux.fppvy = dk2nu.ppvy; -// flux.fppvz = dk2nu.ppvz; - -// flux.ftvx = dk2nu.tgtexit.tvx; -// flux.ftvy = dk2nu.tgtexit.tvy; -// flux.ftvz = dk2nu.tgtexit.tvz; -// flux.ftpx = dk2nu.tgtexit.tpx; -// flux.ftpy = dk2nu.tgtexit.tpy; -// flux.ftpz = dk2nu.tgtexit.tpz; -// flux.ftptype = dk2nu.tgtexit.tptype; -// flux.ftgen = dk2nu.tgtexit.tgen; - -// flux.frun = dk2nu.job; -// flux.fevtno = dk2nu.potnum; -// flux.ftgptype = dk2nu.ancestor[1].pdg; - -// // flux.fnenergyn = flux.fnenergyf = enu; -// // flux.fnwtnear = flux.fnwtfar = wgt; -// // ignore variables dealing with the neutrino -// flux.fnenergyn = -1; -// flux.fnwtnear = flux.fnwtfar = -1; -// flux.fdk2gen = -1; - -// // placeholder for time -// flux.fxpoint = dk2nu.ancestor.back().startt; - -// return flux; -// } - - -// DEFINE_ART_CLASS_TOOL(BNBKaonGen) - -// } // namespace ldm -// } // namespace evgen - - -/** - * - */ - -// Framework Includes -#include "art/Framework/Core/EDProducer.h" -#include "art/Framework/Principal/Event.h" -#include "art/Framework/Principal/Handle.h" -#include "art/Framework/Services/Registry/ServiceHandle.h" -#include "art/Persistency/Common/PtrMaker.h" -#include "art/Utilities/ToolMacros.h" -#include "cetlib/cpu_timer.h" -#include "fhiclcpp/ParameterSet.h" -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "CLHEP/Random/RandFlat.h" -#include "ifdh_art/IFDHService/IFDH_service.h" - -#include "nusimdata/SimulationBase/MCFlux.h" - -// local includes -#include "IMesonGen.h" -#include "boone.h" -#include "PDGCodes.h" - -// LArSoft includes -#include "dk2nu/tree/dk2nu.h" -#include "dk2nu/tree/dkmeta.h" -#include "dk2nu/tree/NuChoice.h" - -// ROOT -#include "TVector3.h" -#include "TTree.h" -#include "TFile.h" -#include "TTreeReader.h" -#include "TTreeReaderValue.h" - -// std includes -#include -#include -#include - -//------------------------------------------------------------------------------------------------------------------------------------------ -// implementation follows - -namespace evgen { -namespace ldm { - -/** - * @brief BNBKaonGenDK2NU class definition - */ -class BNBKaonGenDK2NU : public IMesonGen -{ -public: - BNBKaonGenDK2NU(fhicl::ParameterSet const &pset); - ~BNBKaonGenDK2NU(); - - double GetPOT() override; - simb::MCFlux GetNext() override; - - void configure(const fhicl::ParameterSet&) override; - - // Unified interface - void GetNextEntry(); - simb::MCFlux BuildMCFlux(); - - std::vector LoadFluxFiles(); - simb::MCFlux MakeMCFlux(const bsim::Dk2Nu &dk2nu); - simb::MCFlux MakeMCFlux(const bsim::BooNe &boone); - double LoadPOT(); - - // no weights - double MaxWeight() override { return -1.; } - -private: - // ------------------------ - // Configuration parameters - // ------------------------ - std::string fSearchPath; - std::vector fSearchPatterns; - unsigned long fMaxFluxFileMB; - std::string fFluxCopyMethod; - bool fRandomizeFiles; - bool fVerbose; - - std::string fTreeName; - std::string fMetaTreeName; - std::string fFluxMode; // BooNE or Dk2Nu - - // ------------------------ - // File tracking - // ------------------------ - unsigned fFileIndex; - bool fNewFile; - std::vector fFluxFiles; - - // ------------------------ - // Entry tracking - // ------------------------ - unsigned fEntry; - unsigned fEntryStart; - - // ------------------------ - // ROOT holders - // ------------------------ - TTree *fFluxTree; - TFile *fFluxFile; - bsim::Dk2Nu *fDk2Nu; - bsim::BooNe *fBooNe; - - bool fBranchesInitialized = false; - - // ------------------------ - // POT accounting - // ------------------------ - double fAccumulatedPOT; - double fThisFilePOT; - - // Internal helpers - void InitBranches(); -}; - -// ============================================================================ -// Constructor -// ============================================================================ - -BNBKaonGenDK2NU::BNBKaonGenDK2NU(fhicl::ParameterSet const &pset): - IMeVPrtlStage("BNBKaonGenDK2NU") -{ - configure(pset); - - // Copy the flux files locally - fFluxFiles = LoadFluxFiles(); - - // Initialize indices - fFileIndex = 0; - fEntry = 0; - fEntryStart = 0; - fNewFile = true; - fFluxTree = nullptr; - fFluxFile = nullptr; - - // Allocate buffers - fDk2Nu = new bsim::Dk2Nu; - fBooNe = new bsim::BooNe; - - fAccumulatedPOT = 0.; - fThisFilePOT = 0.; -} - -// ============================================================================ -// Destructor -// ============================================================================ - -BNBKaonGenDK2NU::~BNBKaonGenDK2NU() -{ - if (fDk2Nu) delete fDk2Nu; - if (fBooNe) delete fBooNe; -} - -// ============================================================================ -// Configure -// ============================================================================ - -void BNBKaonGenDK2NU::configure(fhicl::ParameterSet const &pset) -{ - fSearchPath = pset.get("SearchPath"); - fSearchPatterns = pset.get>("FluxFiles"); - fMaxFluxFileMB = pset.get("MaxFluxFileMB", 2 * 1024); - fFluxCopyMethod = pset.get("FluxCopyMethod", "IFDH"); - fTreeName = pset.get("TreeName"); - fMetaTreeName = pset.get("MetaTreeName"); - fRandomizeFiles = pset.get("RandomizeFiles"); - fVerbose = pset.get("Verbose", true); - - // Read flux mode from FHiCL - fFluxMode = pset.get("FluxMode", "BooNE"); - - // Normalize user input - if (fFluxMode == "boone") fFluxMode = "BooNE"; - else if (fFluxMode == "dk2nu") fFluxMode = "Dk2Nu"; - - // Validate mode - if (fFluxMode != "BooNE" && fFluxMode != "Dk2Nu") { - throw cet::exception("BNBKaonGenDK2NU") - << "Invalid FluxMode = " << fFluxMode - << " (allowed values: BooNE, Dk2Nu)"; - } - - // Log confirmation - mf::LogInfo("BNBKaonGenDK2NU") - << "============================================\n" - << " BNBKaonGenDK2NU running in FluxMode = " << fFluxMode << "\n" - << "============================================"; - - if (fVerbose) { - std::cout << "Searching for flux files at path: " << fSearchPath << std::endl; - std::cout << "With patterns:\n"; - for (const std::string &s: fSearchPatterns) std::cout << s << std::endl; - std::cout << "With copy method: " << fFluxCopyMethod << std::endl; - } -} - -// ============================================================================ -// Initialize ROOT branches depending on FluxMode -// ============================================================================ - -void BNBKaonGenDK2NU::InitBranches() -{ - if (fBranchesInitialized) return; - - if (!fFluxTree) { - throw cet::exception("BNBKaonGenDK2NU") << "Flux tree is not initialized"; - } - - if (fFluxMode == "Dk2Nu") { - // Bind dk2nu branch only in Dk2Nu mode - fFluxTree->SetBranchAddress("dk2nu", &fDk2Nu); - mf::LogInfo("BNBKaonGenDK2NU") << "Initialized dk2nu branch"; - } - else { - // BooNE reader manages its own file access - mf::LogInfo("BNBKaonGenDK2NU") << "Using BooNE reader (no ROOT branch binding)"; - } - - fBranchesInitialized = true; -} - -// ============================================================================ -// Load flux files -// ============================================================================ - -std::vector BNBKaonGenDK2NU::LoadFluxFiles() -{ - art::ServiceHandle ifdhp; - - std::vector> allFiles; - - // Find all matching flux files - for (unsigned i = 0; i < fSearchPatterns.size(); i++) { - auto thisList = ifdhp->findMatchingFiles(fSearchPath, fSearchPatterns[i]); - std::copy(thisList.begin(), thisList.end(), std::back_inserter(allFiles)); - } - - // Randomize file order if requested - std::vector order(allFiles.size(), 0); - if (fRandomizeFiles) { - std::vector rand(allFiles.size(), 0.); - CLHEP::RandFlat::shootArray(fEngine, rand.size(), &rand[0]); - TMath::Sort(allFiles.size(), &rand[0], &order[0], false); - } - else { - for (unsigned i = 0; i < order.size(); i++) { - order[i] = i; - } - } - - // Direct access mode - if (fFluxCopyMethod == "DIRECT") { - if (fVerbose) std::cout << "DIRECTLY ACCESSING FLUX FILES.\n"; - std::vector files(allFiles.size()); - for (unsigned i = 0; i < order.size(); i++) { - files[i] = allFiles[order[i]].first; - } - return files; - } - - // Copy files up to size limit - std::vector> selected; - unsigned long totalBytes = 0; - unsigned ind = 0; - while (totalBytes < (fMaxFluxFileMB * 1024 * 1024) && ind < allFiles.size()) { - selected.push_back(allFiles[order[ind]]); - totalBytes += allFiles[order[ind]].second; - ind++; - } - - // Copy files locally - auto localFiles = ifdhp->fetchSharedFiles(selected, fFluxCopyMethod); - - std::vector files(localFiles.size()); - for (unsigned i = 0; i < localFiles.size(); i++) { - files[i] = localFiles[i].first; - } - - return files; -} - -// ============================================================================ -// Load POT from metadata tree -// ============================================================================ - -double BNBKaonGenDK2NU::LoadPOT() -{ - TTreeReader metaReader(fMetaTreeName.c_str(), fFluxFile); - TTreeReaderValue pot(metaReader, "pots"); - - double total_pot = 0.; - while (metaReader.Next()) { - total_pot += *pot; - } - return total_pot; -} - -// ============================================================================ -// Return accumulated POT -// ============================================================================ - -double BNBKaonGenDK2NU::GetPOT() -{ - double ret = fAccumulatedPOT; - fAccumulatedPOT = 0.; - return ret; -} - -// ============================================================================ -// Unified GetNextEntry -// ============================================================================ - -void BNBKaonGenDK2NU::GetNextEntry() -{ - // Open new file if needed - if (fNewFile) { - - if (fFileIndex >= fFluxFiles.size()) { - fFileIndex = 0; - } - - if (fVerbose) { - std::cout << "New file: " << fFluxFiles[fFileIndex] - << " at index: " << fFileIndex - << " of: " << fFluxFiles.size() << std::endl; - } - - if (fFluxFile) delete fFluxFile; - fFluxFile = new TFile(fFluxFiles[fFileIndex].c_str()); - fFluxTree = (TTree*)fFluxFile->Get(fTreeName.c_str()); - - if (!fFluxTree) { - throw cet::exception("BNBKaonGenDK2NU") - << "Could not load tree " << fTreeName; - } - - // Initialize branches depending on mode - InitBranches(); - - // BooNE reader must be re-created per file - if (fFluxMode == "BooNE") { - if (fBooNe) delete fBooNe; - fBooNe = new bsim::BooNe(fFluxFiles[fFileIndex].c_str()); - } - - // Start at a random entry in this file - fEntryStart = CLHEP::RandFlat::shootInt( - fEngine, fFluxTree->GetEntries() - 1); - - fEntry = fEntryStart; - - // Load POT only for Dk2Nu mode - if (fFluxMode == "Dk2Nu") { - fThisFilePOT = LoadPOT(); - } - - fNewFile = false; - } - else { - fEntry = (fEntry + 1) % fFluxTree->GetEntries(); - - // If last entry was reached, move to next file - if ((fEntry + 1) % fFluxTree->GetEntries() == fEntryStart) { - fFileIndex++; - fNewFile = true; - } - } - - // Read current entry from ROOT tree - fFluxTree->GetEntry(fEntry); - - // Mode-dependent handling - if (fFluxMode == "BooNE") { - - fBooNe->myNtuple.run = fEntry; - fBooNe->myNtuple.eventn = fFileIndex; - fBooNe->GetEntry(fEntry); - - // Accumulate POT from BooNE - fAccumulatedPOT += fBooNe->GetPOT(); - } - else { - // Dk2Nu POT is evenly distributed per entry - fAccumulatedPOT += fThisFilePOT / fFluxTree->GetEntries(); - } -} - -// ============================================================================ -// Build MCFlux according to FluxMode -// ============================================================================ - -simb::MCFlux BNBKaonGenDK2NU::BuildMCFlux() -{ - if (fFluxMode == "BooNE") { - return MakeMCFlux(*fBooNe); - } - else { - return MakeMCFlux(*fDk2Nu); - } -} - -// ============================================================================ -// GetNext (public interface) -// ============================================================================ - -simb::MCFlux BNBKaonGenDK2NU::GetNext() -{ - GetNextEntry(); - return BuildMCFlux(); -} - -// ============================================================================ -// MakeMCFlux overloads -// ============================================================================ - -// --- BooNE version --- -simb::MCFlux BNBKaonGenDK2NU::MakeMCFlux(const bsim::BooNe &boone) -{ - simb::MCFlux flux; - auto fBooneNtp = boone.myNtuple; - - - - - if ( fBooneNtp.ntp == 1 ) { - flux.fntype = 12; //nue - } - else if ( fBooneNtp.ntp == 2 ) { - flux.fntype = -12; //nuebar - } - else if ( fBooneNtp.ntp == 3 ) { - flux.fntype = 14; //numu - } - else if ( fBooneNtp.ntp == 4 ) { - flux.fntype = -14; //numubar - } - else{ - mf::LogWarning("BooNEInterface") << "Neutrino type not recognized! ntp = " << fBooneNtp.ntp - << std::endl; - } - - flux.fFluxType = simb::kDk2Nu; - flux.fnimpwt = fBooneNtp.beamwgt; - flux.fvx = fBooneNtp.ini_pos[0][0]; //0 - flux.fvy = fBooneNtp.ini_pos[0][1]; //0 - flux.fvz = fBooneNtp.ini_pos[0][2]; //0 - flux.fpdpx = fBooneNtp.fin_mom[1][0]; //1 final - flux.fpdpy = fBooneNtp.fin_mom[1][1]; //1 final - flux.fpdpz = fBooneNtp.fin_mom[1][2]; //1 final - flux.fpppz = fBooneNtp.ini_mom[1][2]; //1 init - - // Momentum projected in dx/dz or dy/dz - flux.fpppz = fBooneNtp.ini_mom[1][2]; //1 init - double pppx = fBooneNtp.ini_mom[1][0]; //1 init - double pppy = fBooneNtp.ini_mom[1][1]; //1 init - double apppz = flux.fpppz; - if (TMath::Abs(flux.fpppz) < 1.0e-30) apppz = 1.0e-30; - flux.fppdxdz = pppx / apppz; - flux.fppdydz = pppy / apppz; - - flux.fppmedium = 0.; - flux.fppenergy = fBooneNtp.ini_eng[1]; - - int npart = fBooneNtp.npart; - int ptype_input = fBooneNtp.id[1]; - int tptype_input = fBooneNtp.id[npart-2]; - - if (ptype_input != 0) ptype_input = evgen::GeantToPdg(ptype_input); - if (tptype_input != 0) tptype_input= evgen::GeantToPdg(tptype_input); - - flux.fptype = ptype_input; - flux.ftptype = tptype_input; - - ///// - // Now need to calculate ndecay - ///// - - double Nenergy = fBooneNtp.ini_eng[0]; - double Ndxdz = fBooneNtp.ini_mom[0][0] / fBooneNtp.ini_mom[0][2]; - double Ndydz = fBooneNtp.ini_mom[0][1] / fBooneNtp.ini_mom[0][2]; - - double ppenergy = fBooneNtp.ini_eng[1]; - double pdPx = fBooneNtp.fin_mom[1][0]; - double pdPy = fBooneNtp.fin_mom[1][1]; - double pdPz = fBooneNtp.fin_mom[1][2]; - - double ppdxdz = fBooneNtp.ini_mom[1][0] / fBooneNtp.ini_mom[1][2]; - double ppdydz = fBooneNtp.ini_mom[1][1] / fBooneNtp.ini_mom[1][2]; - double pppz = fBooneNtp.ini_mom[1][2]; - - // Get the neutrino energy in the parent decay cm - double parent_mass = std::sqrt(ppenergy * ppenergy - - pppz * pppz * (ppdxdz * ppdxdz + - ppdydz * ppdydz + - 1.)); - - double parent_energy = std::sqrt(pdPx * pdPx + - pdPy * pdPy + - pdPz * pdPz + - parent_mass * parent_mass); - - double gamma = parent_energy / parent_mass; - double beta[3]; - beta[0] = pdPx / parent_energy; - beta[1] = pdPy / parent_energy; - beta[2] = pdPz / parent_energy; - - double partial = fBooneNtp.ini_mom[0][2] * gamma * - (beta[0] * Ndxdz + - beta[1] * Ndydz + - beta[2]); - - double Necm = gamma * Nenergy - partial; - - if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 1) flux.fndecay = 1; - else if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 2) flux.fndecay = 2; - else if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 3) flux.fndecay = 3; - else if (fBooneNtp.id[1] == 10 && fBooneNtp.ntp == 4) flux.fndecay = 4; - else if (fBooneNtp.id[1] == 11 && fBooneNtp.ntp == 3) { - //check if it is a two or three body decay - if (fabs((parent_mass*parent_mass-0.105658389*0.105658389)/(2.*parent_mass)-Necm)/Necm <= 0.001) - //two body decay (numu + mu+) - flux.fndecay = 5; - else { - //three body decay (numu + pi0 + mu+) - flux.fndecay = 7; - } - } - else if (fBooneNtp.id[1] == 11 && fBooneNtp.ntp == 1) flux.fndecay = 6; - else if (fBooneNtp.id[1] == 12 && fBooneNtp.ntp == 4) { - if (fabs((parent_mass*parent_mass-0.105658389*0.105658389)/(2.*parent_mass)-Necm)/Necm <= 0.001) { - //two body decay (numu + mu+) - flux.fndecay = 8; - } - else { - //three body decay (numu + pi0 + mu+) - flux.fndecay = 10; - } - } - else if (fBooneNtp.id[1] == 12 && fBooneNtp.ntp == 2) flux.fndecay = 9; - else if (fBooneNtp.id[1] == 5 ) flux.fndecay = 11; - else if (fBooneNtp.id[1] == 6 ) flux.fndecay = 12; - else if (fBooneNtp.id[1] == 8 ) flux.fndecay = 13; - else if (fBooneNtp.id[1] == 9 ) flux.fndecay = 14; - - ///// - // End calculation of ndecay - ///// - double mupare; - double muparpx; - double muparpy; - double muparpz; - - if ( fBooneNtp.id[1] == 5 || fBooneNtp.id[1] == 6) { - mupare = fBooneNtp.ini_eng[2]; - muparpx = fBooneNtp.fin_mom[2][0]; - muparpy = fBooneNtp.fin_mom[2][1]; - muparpz = fBooneNtp.fin_mom[2][2]; - } else { - mupare = -9999.; - muparpx = -9999.; - muparpy = -9999.; - muparpz = -9999.; - } - - flux.fmuparpx = muparpx; - flux.fmuparpy = muparpy; - flux.fmuparpz = muparpz; - flux.fmupare = mupare; - - flux.fnecm = Necm; - - flux.fppvx = fBooneNtp.ini_pos[1][0]; - flux.fppvy = fBooneNtp.ini_pos[1][1]; - flux.fppvz = fBooneNtp.ini_pos[1][2]; - - flux.ftvx = fBooneNtp.ini_pos[npart-2][0]; - flux.ftvy = fBooneNtp.ini_pos[npart-2][1]; - flux.ftvz = fBooneNtp.ini_pos[npart-2][2]; - flux.ftpx = fBooneNtp.ini_mom[npart-2][0]; - flux.ftpy = fBooneNtp.ini_mom[npart-2][1]; - flux.ftpz = fBooneNtp.ini_mom[npart-2][2]; - // flux.ftgen = dk2nu.tgtexit.tgen; - - flux.frun = fBooneNtp.run; - flux.fevtno = fBooneNtp.eventn; - flux.ftgptype = evgen::GeantToPdg(fBooneNtp.id[npart-2]); - - // flux.fnenergyn = flux.fnenergyf = enu; - // flux.fnwtnear = flux.fnwtfar = wgt; - // ignore variables dealing with the neutrino - flux.fnenergyn = -1; - flux.fnwtnear = flux.fnwtfar = -1; - flux.fdk2gen = -1; - - // // placeholder for time - flux.fxpoint = fBooneNtp.ini_t[0]; - - return flux; -} - -// --- Dk2Nu version --- -simb::MCFlux BNBKaonGenDK2NU::MakeMCFlux(const bsim::Dk2Nu &dk2nu) -{ - simb::MCFlux flux; - - flux.fFluxType = simb::kDk2Nu; - flux.fntype = dk2nu.decay.ntype; - flux.fnimpwt = dk2nu.decay.nimpwt; - flux.fvx = dk2nu.decay.vx; - flux.fvy = dk2nu.decay.vy; - flux.fvz = dk2nu.decay.vz; - flux.fpdpx = dk2nu.decay.pdpx; - flux.fpdpy = dk2nu.decay.pdpy; - flux.fpdpz = dk2nu.decay.pdpz; - flux.fppdxdz = dk2nu.decay.ppdxdz; - flux.fppdydz = dk2nu.decay.ppdydz; - flux.fpppz = dk2nu.decay.pppz; - flux.fppenergy = dk2nu.decay.ppenergy; - flux.fppmedium = dk2nu.decay.ppmedium; - flux.fptype = dk2nu.decay.ptype; - flux.fndecay = dk2nu.decay.ndecay; - flux.fmuparpx = dk2nu.decay.muparpx; - flux.fmuparpy = dk2nu.decay.muparpy; - flux.fmuparpz = dk2nu.decay.muparpz; - flux.fmupare = dk2nu.decay.mupare; - flux.fnecm = dk2nu.decay.necm; - - flux.fppvx = dk2nu.ppvx; - flux.fppvy = dk2nu.ppvy; - flux.fppvz = dk2nu.ppvz; - - flux.ftvx = dk2nu.tgtexit.tvx; - flux.ftvy = dk2nu.tgtexit.tvy; - flux.ftvz = dk2nu.tgtexit.tvz; - flux.ftpx = dk2nu.tgtexit.tpx; - flux.ftpy = dk2nu.tgtexit.tpy; - flux.ftpz = dk2nu.tgtexit.tpz; - flux.ftptype = dk2nu.tgtexit.tptype; - flux.ftgen = dk2nu.tgtexit.tgen; - - flux.frun = dk2nu.job; - flux.fevtno = dk2nu.potnum; - flux.ftgptype = dk2nu.ancestor[1].pdg; - - // flux.fnenergyn = flux.fnenergyf = enu; - // flux.fnwtnear = flux.fnwtfar = wgt; - // ignore variables dealing with the neutrino - flux.fnenergyn = -1; - flux.fnwtnear = flux.fnwtfar = -1; - flux.fdk2gen = -1; - - // placeholder for time - flux.fxpoint = dk2nu.ancestor.back().startt; - - return flux; -} - -DEFINE_ART_CLASS_TOOL(BNBKaonGenDK2NU) - -} // namespace ldm -} // namespace evgen From 18df35821440a93bbd0b41abddf1b16f8c21ba27 Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Wed, 29 Apr 2026 15:21:56 +0200 Subject: [PATCH 10/14] Delete sbncode/EventGenerator/MeVPrtl/Tools/BNBPi0Gen_tool.cc Not intended to be part of branch --- .../MeVPrtl/Tools/BNBPi0Gen_tool.cc | 332 ------------------ 1 file changed, 332 deletions(-) delete mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/BNBPi0Gen_tool.cc diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/BNBPi0Gen_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/BNBPi0Gen_tool.cc deleted file mode 100644 index 7b5c3feff..000000000 --- a/sbncode/EventGenerator/MeVPrtl/Tools/BNBPi0Gen_tool.cc +++ /dev/null @@ -1,332 +0,0 @@ -/** - * - */ - -// Framework Includes -#include "art/Framework/Core/EDProducer.h" -#include "art/Framework/Principal/Event.h" -#include "art/Framework/Principal/Handle.h" -#include "art/Framework/Services/Registry/ServiceHandle.h" -#include "art/Persistency/Common/PtrMaker.h" -#include "art/Utilities/ToolMacros.h" -#include "cetlib/cpu_timer.h" -#include "fhiclcpp/ParameterSet.h" -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "CLHEP/Random/RandFlat.h" -#include "ifdh_art/IFDHService/IFDH_service.h" - -#include "nusimdata/SimulationBase/MCFlux.h" - -// local includes -#include "IMesonGen.h" - -// LArSoft includes -#include "dk2nu/tree/dk2nu.h" -#include "dk2nu/tree/dkmeta.h" -#include "dk2nu/tree/NuChoice.h" - -// ROOT -#include "TVector3.h" -#include "TTree.h" -#include "TFile.h" -#include "TTreeReader.h" -#include "TTreeReaderValue.h" - -// std includes -#include -#include -#include - -//------------------------------------------------------------------------------------------------------------------------------------------ -// implementation follows - -namespace evgen { -namespace ldm { -/** - * @brief BNBPi0Gen class definiton - */ -class BNBPi0Gen : public IMesonGen -{ -public: - /** - * @brief Constructor - */ - BNBPi0Gen(fhicl::ParameterSet const &pset); - - /** - * @brief Destructor - */ - ~BNBPi0Gen(); - - double GetPOT() override; - simb::MCFlux GetNext() override; - - void configure(const fhicl::ParameterSet&) override; - - const bsim::Dk2Nu *GetNextEntry(); - std::vector LoadFluxFiles(); - simb::MCFlux MakeMCFlux(const bsim::Dk2Nu &dk2nu); - double LoadPOT(); - - // no weights - double MaxWeight() override { return -1.; } - -private: - // config - std::string fSearchPath; - std::vector fSearchPatterns; - unsigned long fMaxFluxFileMB; - std::string fFluxCopyMethod; - bool fRandomizeFiles; - - std::string fTreeName; - std::string fMetaTreeName; - - // info for tracking files - unsigned fFileIndex; - bool fNewFile; - std::vector fFluxFiles; - - // info for tracking entry in file - unsigned fEntry; - unsigned fEntryStart; - - // ROOT Holders - TTree *fFluxTree; - TFile *fFluxFile; - bsim::Dk2Nu *fDk2Nu; - - // count POT - double fAccumulatedPOT; - double fThisFilePOT; - -}; - -BNBPi0Gen::BNBPi0Gen(fhicl::ParameterSet const &pset): - IMeVPrtlStage("BNBPi0Gen") -{ - configure(pset); - - // copy the flux files locally - fFluxFiles = LoadFluxFiles(); - - // setup indices - fFileIndex = 0; - fEntry = 0; - fEntryStart = 0; - fNewFile = true; - fFluxTree = NULL; - fFluxFile = NULL; - fDk2Nu = new bsim::Dk2Nu; - - fAccumulatedPOT = 0.; - fThisFilePOT = 0.; - -} - -//------------------------------------------------------------------------------------------------------------------------------------------ - -BNBPi0Gen::~BNBPi0Gen() -{ - - if (fDk2Nu) delete fDk2Nu; -} - -//------------------------------------------------------------------------------------------------------------------------------------------ -void BNBPi0Gen::configure(fhicl::ParameterSet const &pset) -{ - fSearchPath = pset.get("SearchPath"); - fSearchPatterns = pset.get>("FluxFiles"); - fMaxFluxFileMB = pset.get("MaxFluxFileMB", 2 * 1024); - fFluxCopyMethod = pset.get("FluxCopyMethod", "IFDH"); - fTreeName = pset.get("TreeName"); - fMetaTreeName = pset.get("MetaTreeName"); - fRandomizeFiles = pset.get("RandomizeFiles"); - - std::cout << "Searching for flux files at path: " << fSearchPath << std::endl; - std::cout << "With patterns:\n"; - for (const std::string &s: fSearchPatterns) std::cout << s << std::endl; - std::cout << "With copy method: " << fFluxCopyMethod << std::endl; -} - -std::vector BNBPi0Gen::LoadFluxFiles() { - art::ServiceHandle ifdhp; - - std::vector> allFiles; - - // find the flux files - for (unsigned i = 0; i < fSearchPatterns.size(); i++) { - std::vector> thisList = ifdhp->findMatchingFiles(fSearchPath, fSearchPatterns[i]); - std::copy (thisList.begin(), thisList.end(), std::back_inserter(allFiles)); - } - - // first randomize the flux files - std::vector order(allFiles.size(), 0); - if (fRandomizeFiles) { - std::vector rand(allFiles.size(), 0.); - CLHEP::RandFlat::shootArray(fEngine, rand.size(), &rand[0]); - TMath::Sort(allFiles.size(), &rand[0], &order[0], false); - } - else { - for (unsigned i = 0; i < order.size(); i++) { - order[i] = i; - } - } - - // If we are directly accessing the files, no need to copy - if (fFluxCopyMethod == "DIRECT") { - std::cout << "DIRECTLY ACCESSING FLUX FILES.\n"; - std::vector files(allFiles.size()); - for (unsigned i = 0; i < order.size(); i++) { - files[i] = allFiles[order[i]].first; - } - return files; - } - - // copy over up to the provided limit - std::vector> selected; - unsigned long totalBytes = 0; - unsigned ind = 0; - while (totalBytes < (fMaxFluxFileMB * 1024 * 1024) && ind < allFiles.size()) { - selected.push_back(allFiles[order[ind]]); - totalBytes += allFiles[order[ind]].second; - ind ++; - } - - // copy the files locally - std::vector> localFiles = ifdhp->fetchSharedFiles(selected, fFluxCopyMethod); - - std::vector files(localFiles.size()); - for (unsigned i = 0; i < localFiles.size(); i++) { - files[i] = localFiles[i].first; - } - - return files; -} - -double BNBPi0Gen::LoadPOT() { - TTreeReader metaReader(fMetaTreeName.c_str(), fFluxFile); - TTreeReaderValue pot(metaReader, "pots"); - - double total_pot = 0.; - - while (metaReader.Next()) { - total_pot += *pot; - } - - return total_pot; -} - - -double BNBPi0Gen::GetPOT() { - double ret = fAccumulatedPOT; - fAccumulatedPOT = 0.; - return ret; -} - -const bsim::Dk2Nu *BNBPi0Gen::GetNextEntry() { - // new file -- set the start entry - if (fNewFile) { - // wrap file index around - //if (fFileIndex >= fFluxFiles.size()) { - // fFileIndex = 0; - //} - if (fFileIndex >= fFluxFiles.size()) { - throw cet::exception("FluxReader Out of Files", - "At file index (" + std::to_string(fFileIndex) + ") of available files (" + std::to_string(fFluxFiles.size()) + ")."); - } - - std::cout << "New file: " << fFluxFiles[fFileIndex] << " at index: " << fFileIndex << " of: " << fFluxFiles.size() << std::endl; - if (fFluxFile) delete fFluxFile; - fFluxFile = new TFile(fFluxFiles[fFileIndex].c_str()); - fFluxTree = (TTree*)fFluxFile->Get(fTreeName.c_str()); - fFluxTree->SetBranchAddress("dk2nu",&fDk2Nu); - - // Start at a random index in this file - fEntryStart = CLHEP::RandFlat::shootInt(fEngine, fFluxTree->GetEntries()-1); - fEntry = fEntryStart; - - // load the POT in this file - fThisFilePOT = LoadPOT(); - fNewFile = false; - } - else { - fEntry = (fEntry + 1) % fFluxTree->GetEntries(); - // if this is the last entry, get ready for the next file - if ((fEntry + 1) % fFluxTree->GetEntries() == fEntryStart) { - fFileIndex ++; - fNewFile = true; - } - } - - // count the POT - fAccumulatedPOT += fThisFilePOT / fFluxTree->GetEntries(); - - fFluxTree->GetEntry(fEntry); - return fDk2Nu; -} - -simb::MCFlux BNBPi0Gen::GetNext() { - const bsim::Dk2Nu *flux = GetNextEntry(); - return MakeMCFlux(*flux); -} - -simb::MCFlux BNBPi0Gen::MakeMCFlux(const bsim::Dk2Nu &dk2nu) { - simb::MCFlux flux; - - flux.fFluxType = simb::kDk2Nu; - flux.fntype = -1; //dk2nu.decay.ntype; - flux.fnimpwt = dk2nu.decay.nimpwt; - flux.fvx = dk2nu.decay.vx; - flux.fvy = dk2nu.decay.vy; - flux.fvz = dk2nu.decay.vz; - flux.fpdpx = dk2nu.decay.pdpx; - flux.fpdpy = dk2nu.decay.pdpy; - flux.fpdpz = dk2nu.decay.pdpz; - flux.fppdxdz = dk2nu.decay.ppdxdz; - flux.fppdydz = dk2nu.decay.ppdydz; - flux.fpppz = dk2nu.decay.pppz; - flux.fppenergy = dk2nu.decay.ppenergy; - flux.fppmedium = dk2nu.decay.ppmedium; - flux.fptype = dk2nu.decay.ptype; - flux.fndecay = dk2nu.decay.ndecay; - flux.fmuparpx = dk2nu.decay.muparpx; - flux.fmuparpy = dk2nu.decay.muparpy; - flux.fmuparpz = dk2nu.decay.muparpz; - flux.fmupare = dk2nu.decay.mupare; - flux.fnecm = dk2nu.decay.necm; - - flux.fppvx = dk2nu.ppvx; - flux.fppvy = dk2nu.ppvy; - flux.fppvz = dk2nu.ppvz; - - flux.ftvx = dk2nu.tgtexit.tvx; - flux.ftvy = dk2nu.tgtexit.tvy; - flux.ftvz = dk2nu.tgtexit.tvz; - flux.ftpx = dk2nu.tgtexit.tpx; - flux.ftpy = dk2nu.tgtexit.tpy; - flux.ftpz = dk2nu.tgtexit.tpz; - flux.ftptype = dk2nu.tgtexit.tptype; - flux.ftgen = dk2nu.tgtexit.tgen; - - flux.frun = dk2nu.job; - flux.fevtno = dk2nu.potnum; - flux.ftgptype = dk2nu.ancestor[1].pdg; - - // flux.fnenergyn = flux.fnenergyf = enu; - // flux.fnwtnear = flux.fnwtfar = wgt; - // ignore variables dealing with the neutrino - flux.fnenergyn = -1; - flux.fnwtnear = flux.fnwtfar = -1; - flux.fdk2gen = -1; - - // placeholder for time - flux.fxpoint = dk2nu.ancestor.back().startt; - - return flux; -} - -DEFINE_ART_CLASS_TOOL(BNBPi0Gen) - -} // namespace ldm -} // namespace evgen From 721fa2895a5d7a81a1872bbd0f597624fce60282 Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Wed, 29 Apr 2026 15:22:15 +0200 Subject: [PATCH 11/14] Delete sbncode/EventGenerator/MeVPrtl/Tools/TxtFileGenNM_tool.cc Not intended to be part of branch --- .../MeVPrtl/Tools/TxtFileGenNM_tool.cc | 360 ------------------ 1 file changed, 360 deletions(-) delete mode 100644 sbncode/EventGenerator/MeVPrtl/Tools/TxtFileGenNM_tool.cc diff --git a/sbncode/EventGenerator/MeVPrtl/Tools/TxtFileGenNM_tool.cc b/sbncode/EventGenerator/MeVPrtl/Tools/TxtFileGenNM_tool.cc deleted file mode 100644 index 48276be60..000000000 --- a/sbncode/EventGenerator/MeVPrtl/Tools/TxtFileGenNM_tool.cc +++ /dev/null @@ -1,360 +0,0 @@ -/** - * - */ - -// Framework Includes -#include "art/Framework/Core/EDProducer.h" -#include "art/Framework/Principal/Event.h" -#include "art/Framework/Principal/Handle.h" -#include "art/Framework/Services/Registry/ServiceHandle.h" -#include "art/Persistency/Common/PtrMaker.h" -#include "art/Utilities/ToolMacros.h" -#include "cetlib/cpu_timer.h" -#include "fhiclcpp/ParameterSet.h" -#include "messagefacility/MessageLogger/MessageLogger.h" -#include "CLHEP/Random/RandFlat.h" -#include "ifdh_art/IFDHService/IFDH_service.h" - -#include "nusimdata/SimulationBase/MCFlux.h" - -// local includes -#include "IMesonGen.h" - -// std includes -#include -#include -#include - -//------------------------------------------------------------------------------------------------------------------------------------------ -// implementation follows - -namespace evgen { -namespace ldm { -/** - * @brief TxtFileGenNM class definiton - */ -class TxtFileGenNM : public IMesonGen -{ -public: - /** - * @brief Constructor - */ - TxtFileGenNM(fhicl::ParameterSet const &pset); - - /** - * @brief Destructor - */ - ~TxtFileGenNM(); - - double GetPOT() override; - simb::MCFlux GetNext() override; - - void configure(const fhicl::ParameterSet&) override; - - std::string GetNextEntry(); - std::vector LoadFluxFiles(); - simb::MCFlux MakeMCFlux(std::string line); - - // no weights - double MaxWeight() override { return -1.; } - -private: - // config - std::string fSearchPath; - std::vector fSearchPatterns; - unsigned long fMaxFluxFileMB; - std::string fFluxCopyMethod; - bool fRandomizeFiles; - int fNSkipLines; - bool fVerbose; - - // info for tracking files - unsigned fFileIndex; - bool fNewFile; - std::vector fFluxFiles; - std::ifstream fCurrentFile; - int fCurrentFileLines; - - // info for tracking entry in file - unsigned fEntry; - unsigned fEntryStart; - - // count POT - double fAccumulatedPOT; -}; - -TxtFileGenNM::TxtFileGenNM(fhicl::ParameterSet const &pset): - IMeVPrtlStage("TxtFileGenNM") -{ - configure(pset); - - // copy the flux files locally - fFluxFiles = LoadFluxFiles(); - - // setup indices - fFileIndex = 0; - fEntry = 0; - fEntryStart = 0; - fNewFile = true; - fCurrentFileLines = 0; - - fAccumulatedPOT = 0.; - -} - -//------------------------------------------------------------------------------------------------------------------------------------------ -TxtFileGenNM::~TxtFileGenNM() {} - -//------------------------------------------------------------------------------------------------------------------------------------------ -void TxtFileGenNM::configure(fhicl::ParameterSet const &pset) -{ - fSearchPath = pset.get("SearchPath"); - fSearchPatterns = pset.get>("FluxFiles"); - fMaxFluxFileMB = pset.get("MaxFluxFileMB", 2 * 1024); - fFluxCopyMethod = pset.get("FluxCopyMethod", "IFDH"); - fRandomizeFiles = pset.get("RandomizeFiles"); - fNSkipLines = pset.get("NSkipLines"); - fVerbose = pset.get("Verbose", false); - - std::cout << "Searching for flux files at path: " << fSearchPath << std::endl; - std::cout << "With patterns:\n"; - for (const std::string &s: fSearchPatterns) std::cout << s << std::endl; - std::cout << "With copy method: " << fFluxCopyMethod << std::endl; -} - -std::vector TxtFileGenNM::LoadFluxFiles() { - art::ServiceHandle ifdhp; - - std::vector> allFiles; - - // find the flux files - for (unsigned i = 0; i < fSearchPatterns.size(); i++) { - std::vector> thisList = ifdhp->findMatchingFiles(fSearchPath, fSearchPatterns[i]); - std::copy (thisList.begin(), thisList.end(), std::back_inserter(allFiles)); - } - - // first randomize the flux files - std::vector order(allFiles.size(), 0); - if (fRandomizeFiles) { - std::vector rand(allFiles.size(), 0.); - CLHEP::RandFlat::shootArray(fEngine, rand.size(), &rand[0]); - TMath::Sort(allFiles.size(), &rand[0], &order[0], false); - } - else { - for (unsigned i = 0; i < order.size(); i++) { - order[i] = i; - } - } - - // If we are directly accessing the files, no need to copy - if (fFluxCopyMethod == "DIRECT") { - std::cout << "DIRECTLY ACCESSING FLUX FILES.\n"; - std::vector files(allFiles.size()); - for (unsigned i = 0; i < order.size(); i++) { - files[i] = allFiles[order[i]].first; - } - return files; - } - - // copy over up to the provided limit - std::vector> selected; - unsigned long totalBytes = 0; - unsigned ind = 0; - while (totalBytes < (fMaxFluxFileMB * 1024 * 1024) && ind < allFiles.size()) { - selected.push_back(allFiles[order[ind]]); - totalBytes += allFiles[order[ind]].second; - ind ++; - } - - // copy the files locally - std::vector> localFiles = ifdhp->fetchSharedFiles(selected, fFluxCopyMethod); - - std::vector files(localFiles.size()); - for (unsigned i = 0; i < localFiles.size(); i++) { - files[i] = localFiles[i].first; - } - - return files; -} - -double TxtFileGenNM::GetPOT() { - double ret = fAccumulatedPOT; - fAccumulatedPOT = 0.; - return ret; -} - - - -std::string TxtFileGenNM::GetNextEntry() { - // new file -- set the start entry - if (fNewFile) { - // wrap file index around - if (fFileIndex >= fFluxFiles.size()) { - fFileIndex = 0; - } - - if (fVerbose) std::cout << "New file: " << fFluxFiles[fFileIndex] << " at index: " << fFileIndex << " of: " << fFluxFiles.size() << std::endl; - - if (fCurrentFile.is_open()) fCurrentFile.close(); - fCurrentFile.clear(); - fCurrentFile.open(fFluxFiles[fFileIndex]); - - if (!fCurrentFile.is_open()) { - throw cet::exception("TxtFileGenNM") - << "Could not open file " << fFluxFiles[fFileIndex]; - } - - // count the number of lines - std::string line; - int lines; - for(lines = 0; std::getline(fCurrentFile,line); lines++); - - fCurrentFileLines = lines - fNSkipLines; - if (fCurrentFileLines <= 0) { - throw cet::exception("TxtFileGenNM") - << "File " << fFluxFiles[fFileIndex] - << " has no usable data lines after skipping " - << fNSkipLines << " header lines. " - << "Total lines in file: " << lines; - } - // Seek back to start - fCurrentFile.clear(); - fCurrentFile.seekg(0); - - // Start at a random index in this file - fEntryStart = CLHEP::RandFlat::shootInt(fEngine, fCurrentFileLines); - fEntry = fEntryStart; - - // skip to that line in the file - for (lines = 0; lines < fNSkipLines + (int)fEntryStart && std::getline(fCurrentFile,line); lines++); - - fNewFile = false; - } - else { - fEntry = (fEntry + 1) % fCurrentFileLines; - - // if this is the last entry, get ready for the next file - if ((fEntry + 1) % fCurrentFileLines == fEntryStart) { - fFileIndex ++; - fNewFile = true; - } - } - - // Read the next line, if we are at the end of the file go back to the beginning - /* std::string thisline; - if (!std::getline(fCurrentFile, thisline)) { - - // seek back to start - fCurrentFile.clear(); - fCurrentFile.seekg(0); - - // skip to the first valid line - int lines; - std::string line; - for (lines = 0; lines < fNSkipLines && std::getline(fCurrentFile,line); lines++); - } - - return thisline;*/ - - std::string thisline; - if (!std::getline(fCurrentFile, thisline)) { - - fCurrentFile.clear(); - fCurrentFile.seekg(0); - - int lines; - std::string line; - for (lines = 0; lines < fNSkipLines && std::getline(fCurrentFile, line); ++lines) {} - - if (!std::getline(fCurrentFile, thisline)) { - throw cet::exception("TxtFileGenNM") - << "Failed to read a valid data line from file " - << fFluxFiles[fFileIndex] - << " after rewinding."; - } - } - return thisline; -} - - - -simb::MCFlux TxtFileGenNM::GetNext() { - std::string meson = GetNextEntry(); - return MakeMCFlux(meson); -} - -simb::MCFlux TxtFileGenNM::MakeMCFlux(std::string line) { - // std::cout << "Parsing line: " << line << std::endl; - - // read the 4-vector off the line - double px, py, pz,x, y, z, wgt, start_t; - // int pdgcode; - std::stringstream l4vec(line); - l4vec >> px >> py >> pz >> x >> y >> z >> start_t >> wgt; - - if (fVerbose) std::cout << "Values: " << px << py << pz << x << y << z << start_t << wgt << std::endl; - - simb::MCFlux flux; - - flux.fFluxType = simb::kSimple_Flux; // number for file gen.... - flux.fnimpwt = wgt; - flux.fvx = x; // At the target -- TODO is this ok??? - flux.fvy = y; - flux.fvz = z; - flux.fpdpx = px; - flux.fpdpy = py; - flux.fpdpz = pz; - flux.fppdxdz = px/pz; - flux.fppdydz = py/pz; - flux.fpppz = pz; - - double mpi0 = 0.1349768; - double p2 = px*px + py*py + pz*pz; - flux.fppenergy = std::sqrt(p2 + mpi0*mpi0); - - flux.fppmedium = -1; - flux.fptype = 111; - flux.fndecay = -1; - flux.fmuparpx = -1; - flux.fmuparpy = -1; - flux.fmuparpz = -1; - flux.fmupare = -1; - flux.fnecm = -1; - - flux.fppvx = 0.; - flux.fppvy = 0.; - flux.fppvz = 0.; - - flux.ftvx = -1; - flux.ftvy = -1; - flux.ftvz = -1; - flux.ftpx = start_t; - flux.ftpy = -1; - flux.ftpz = -1; - flux.ftptype = -1; - flux.ftgen = -1; - - flux.frun = -1; - flux.fevtno = -1; - flux.ftgptype = -1; - - // flux.fnenergyn = flux.fnenergyf = enu; - // flux.fnwtnear = flux.fnwtfar = wgt; - // ignore variables dealing with the neutrino - flux.fnenergyn = -1; - flux.fnwtnear = flux.fnwtfar = -1; - flux.fdk2gen = -1; - - // placeholder for time - flux.fxpoint = 0.; - - // Update the POT - fAccumulatedPOT = 1000000; - - return flux; -} - -DEFINE_ART_CLASS_TOOL(TxtFileGenNM) - -} // namespace ldm -} // namespace evgen From b44ee2d4acbb2c0ae0aac00afdb12f433c8250ef Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Wed, 29 Apr 2026 15:22:29 +0200 Subject: [PATCH 12/14] Delete sbncode/EventGenerator/MeVPrtl/config/DP directory Not intended to be part of branch --- .../MeVPrtl/config/DP/CMakeLists.txt | 1 - .../EventGenerator/MeVPrtl/config/DP/dp.fcl | 99 ------------------- .../MeVPrtl/config/DP/run_dp.fcl | 46 --------- 3 files changed, 146 deletions(-) delete mode 100644 sbncode/EventGenerator/MeVPrtl/config/DP/CMakeLists.txt delete mode 100644 sbncode/EventGenerator/MeVPrtl/config/DP/dp.fcl delete mode 100644 sbncode/EventGenerator/MeVPrtl/config/DP/run_dp.fcl diff --git a/sbncode/EventGenerator/MeVPrtl/config/DP/CMakeLists.txt b/sbncode/EventGenerator/MeVPrtl/config/DP/CMakeLists.txt deleted file mode 100644 index 13355789a..000000000 --- a/sbncode/EventGenerator/MeVPrtl/config/DP/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -install_fhicl() diff --git a/sbncode/EventGenerator/MeVPrtl/config/DP/dp.fcl b/sbncode/EventGenerator/MeVPrtl/config/DP/dp.fcl deleted file mode 100644 index 9e77e6551..000000000 --- a/sbncode/EventGenerator/MeVPrtl/config/DP/dp.fcl +++ /dev/null @@ -1,99 +0,0 @@ -#include "bnb_dp_sbnd.fcl" - -BEGIN_PROLOG - -# ===== parameters you vary ===== -scalarM: 0.30 # GeV -CTau_cm: 100000 # c*tau in cm -BR_ee: 1.0 # BR(A -> e+e-) - -meson_energy: 8 - -epsilon: 1e-7 - -# ====================== -# FLUX: meson -> gamma + A -# ====================== -meson_flux: { - tool_type: Meson2DP - - M: @local::scalarM - e: @local::epsilon - - - Parents: [221] - CorrectDK2NU: true - SecondarySignConvention: "legacy" - - Beam2DetectorRotation: @local::sbnd_bnb_beam2detector_rotation - BeamOrigin: @local::sbnd_bnb_beam_origin - - SpillTimeConfig: "evgb::EvtTimeFNALBeam booster, dtbucket=18.936, sigma=1.308" - GlobalTimeOffset: 0 - - Verbose: true -} - -# ====================== -# RAYTRACE (same as before) -# ====================== -mxdraytrace: @local::mixedweight_ray_trace_box -mxdraytrace.ReferencePrtlMass: @local::scalarM -mxdraytrace.ReferenceScndPDG: 22 -mxdraytrace.ReferencePrimaryEnergy: @local::meson_energy -mxdraytrace.ReferencePrimPDG: 221 - -# ====================== -# DECAY: A -> ee -# ====================== -scalar_decay: { - tool_type: DPDecay - - AllowElectronDecay: true - AllowMuonDecay: true - AddTimeOfFlight: true - - # NEW required inputs -# CTau_cm: @local::CTau_cm - BR_ee: @local::BR_ee - - # optional MaxWeight precompute (same pattern as before, but uses CTau) - ReferenceRayLength: 7.549834e2 - ReferenceRayDistance: 110e2 - ReferenceMass: @local::scalarM - ReferenceCTau_cm: @local::CTau_cm - ReferenceEnergy: @local::meson_energy - - Epsilon: @local::epsilon - - UseIFDHForTables: false - TableCopyMethod: "DIRECT" - TableSearchPath: "/pnfs/sbnd/persistent/users/rohanr/dp/br/" - TableFiles: [ - "/pnfs/sbnd/persistent/users/rohanr/dp/br/bfrac_dark_photon_e_e.txt", - "/pnfs/sbnd/persistent/users/rohanr/dp/br/bfrac_dark_photon_mu_mu.txt", - "/pnfs/sbnd/persistent/users/rohanr/dp/br/bfrac_dark_photon_hadrons.txt" - ] - - - - Verbose: true -} - -# ====================== -# GENERATOR MODULE (same schema) -# ====================== -dp_generator: { - module_type: MeVPrtlGen - Deweight: false - Produce: true - AnaOutput: true - Verbose: true - - MesonGen: @local::bnb_pi0_v2 - Flux: @local::meson_flux - RayTrace: @local::mxdraytrace - Decay: @local::scalar_decay -} - -END_PROLOG \ No newline at end of file diff --git a/sbncode/EventGenerator/MeVPrtl/config/DP/run_dp.fcl b/sbncode/EventGenerator/MeVPrtl/config/DP/run_dp.fcl deleted file mode 100644 index 93f606848..000000000 --- a/sbncode/EventGenerator/MeVPrtl/config/DP/run_dp.fcl +++ /dev/null @@ -1,46 +0,0 @@ -#include "dp.fcl" -#include "simulationservices_sbnd.fcl" - -process_name: MeVPrtl - -services: { - @table::sbnd_simulation_services - - TFileService: { fileName: "hists_mevprtl.root" } - - IFDH: { } - - NuRandomService: { - service_type: "NuRandomService" - policy: "random" - } -} - -source: { module_type: EmptyEvent } - -physics: { - producers: { - generator: @local::dp_generator - } - - analyzers: { - - } - - simulate: [ generator ] - - stream: [ out ] - - trigger_paths: [ simulate ] - end_paths: [ stream ] -} - -outputs: { - out: { - module_type: RootOutput - fileName: "mevprtl_art.root" - dataTier: "simulated" - compressionLevel: 1 - saveMemoryObjectThreshold: 0 - } -} \ No newline at end of file From 72c09d204782b0cf857fd4083a50814dcc5df659 Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Wed, 29 Apr 2026 15:25:53 +0200 Subject: [PATCH 13/14] Delete sbncode/EventGenerator/MeVPrtl/config/bnb_dp_common.fcl Not intended to be part of branch --- .../MeVPrtl/config/bnb_dp_common.fcl | 62 ------------------- 1 file changed, 62 deletions(-) delete mode 100644 sbncode/EventGenerator/MeVPrtl/config/bnb_dp_common.fcl diff --git a/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_common.fcl b/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_common.fcl deleted file mode 100644 index bc0fb4bb8..000000000 --- a/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_common.fcl +++ /dev/null @@ -1,62 +0,0 @@ -BEGIN_PROLOG - -empty_kaon: { - tool_type: EmptyKaonGen -} - - -bnb_pi0_txt: { - tool_type: "TxtFileGenNM" -# SearchPath: "/pnfs/sbnd/persistent/users/rohanr/beammc/neutral_meson_production_1e6pot_2025_07_07_g4v11.2_qbbc" - SearchPath: "/exp/sbnd/data/users/rohanr/BSM/MeVPrtl" - FluxFiles: ["output_pi0_small.txt"] - RandomizeFiles: true - NSkipLines: 0 - MaxFluxFileMB: 8192 # 8GB - FluxCopyMethod: DIRECT - Verbose: false -} - -bnb_pi0: { - - tool_type: "BNBPi0Gen" - SearchPath: "/pnfs/sbnd/persistent/users/rohanr/beammc/neutral_meson_production_1e6pot_2025_07_07_g4v11.2_qbbc/neutrals_primOnly_20250707/0/" - FluxFiles: ["*.dk2nu.root"] - TreeName: "dk2nuTree" - MetaTreeName: "dkmetaTree" - MaxFluxFileMB: 8192 # 8GB - FluxCopyMethod: DIRECT - RandomizeFiles: false - Verbose: false - -} - -bnb_pi0_v2: { - tool_type: "BNBKaonGenDK2NU" # BooNe or Dk2Nu Ntuples - FluxMode: "Dk2Nu" -# SearchPath: "/cvmfs/sbn.osgstorage.org/pnfs/fnal.gov/usr/sbn/persistent/stash/physics-rodrigoa/bnbflux/" # or "/pnfs/sbnd/persistent/G4BNB/" - SearchPath: "/pnfs/sbnd/persistent/users/rohanr/beammc/neutral_meson_production_1e6pot_2025_07_07_g4v11.2_qbbc/neutrals_primOnly_20250707/0/" - FluxFiles: ["*.dk2nu.root"] - TreeName: "dk2nuTree" - MetaTreeName: "dkmetaTree" - MaxFluxFileMB: 8192 # 8GB - FluxCopyMethod: DIRECT - RandomizeFiles: true - Verbose: false - -} - -bnb_pi0_boone: { - tool_type: "BNBKaonGen" # BooNe Ntuples - SearchPath: "/cvmfs/sbn.osgstorage.org/pnfs/fnal.gov/usr/sbn/persistent/stash/physics-rodrigoa/bnbflux/" - FluxFiles: ["*.root"] - TreeName: "h101" - MetaTreeName: "meta" - MaxFluxFileMB: 8192 # 8GB - FluxCopyMethod: DIRECT - RandomizeFiles: false - Verbose: false -} - - -END_PROLOG From 598ee9b9e9578cdca82652da64581824ee030ec8 Mon Sep 17 00:00:00 2001 From: Rohan Rajagopalan Date: Wed, 29 Apr 2026 15:26:08 +0200 Subject: [PATCH 14/14] Delete sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl Not intended to be part of branch --- .../MeVPrtl/config/bnb_dp_sbnd.fcl | 58 ------------------- 1 file changed, 58 deletions(-) delete mode 100644 sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl diff --git a/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl b/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl deleted file mode 100644 index 8b4ae8b83..000000000 --- a/sbncode/EventGenerator/MeVPrtl/config/bnb_dp_sbnd.fcl +++ /dev/null @@ -1,58 +0,0 @@ -#include "bnb_pi0_common.fcl" - -BEGIN_PROLOG - -sbnd_bnb_beam2detector_rotation: [ 1, 0, 0, - 0, 1, 0, - 0, 0, 1] #bnb to sbnd is in z-direction, only need a translation. - -#sbnd_bnb_beam_origin: [-73.78, 0, -11000] # cm in beam in deterctor frame -sbnd_bnb_beam_origin: [0, 0, 0, 73.78, 0, 11000] # cm in detector in beam frame - -#sbnd detector in det frame -sbnd_detector_box: [-200, 200, -200, 200, 0, 500] #cm -sbnd_bnb_solid_angle_box: 1.3223e-3 #front face / detector distance ^2 = 4*4/110^2 - -sbnd_bnb_solid_angle_cryostat: 0.0133 - - -meson_energy: 8 #GeV Max energy from meson -meson_pdg: 221 #eta - -ray_trace_box: { - tool_type: RayTraceBox - Box: @local::sbnd_detector_box - Verbose: false -} - -rethrow_ray_trace_box: { - tool_type: ReThrowRayTraceBox - Box: @local::sbnd_detector_box - ReferenceLabSolidAngle: @local::sbnd_bnb_solid_angle_box - ReferencePrimaryEnergy: @local::meson_energy - ReferencePrimPDG: @local::meson_pdg - Verbose: false -} - -weighted_ray_trace_box: { - tool_type: WeightedRayTraceBox - Box: @local::sbnd_detector_box - ReferenceLabSolidAngle: @local::sbnd_bnb_solid_angle_box - ReferencePrimaryEnergy: @local::meson_energy - ReferencePrimPDG: @local::meson_pdg - Verbose: false -} - -mixedweight_ray_trace_box: { - tool_type: MixedWeightRayTraceBox - Box: @local::sbnd_detector_box - ReferenceLabSolidAngle: @local::sbnd_bnb_solid_angle_box - ReferencePrimaryEnergy: @local::meson_energy - ReferencePrimPDG: @local::meson_pdg - MaxWeightFudge: 2. - NThrow: 250 - FixNSuccess: false - Verbose: false -} - -END_PROLOG \ No newline at end of file