From e563f786f6fae3975fd02f4ba25e31836978ffeb Mon Sep 17 00:00:00 2001 From: VCLanNguyen Date: Mon, 28 Sep 2026 20:07:53 -0500 Subject: [PATCH 1/4] Fill SRTrueInteraction.prod_time/dk2gen and tag rec.mc.nu.generator in CAFMaker Retrieves the event's Dk2Nu product to fill the new prod_time/dk2gen fields in FillTrueNeutrino, and tags each rec.mc.nu entry's generator as kGENIE, kMeVPrtl, or kUnknownGenerator so downstream code (e.g. a dk2nu vertex-time correction) can scope itself to GENIE-only interactions. --- sbncode/CAFMaker/CAFMaker_module.cc | 23 ++++++++++++++++++++++- sbncode/CAFMaker/CMakeLists.txt | 1 + sbncode/CAFMaker/FillTrue.cxx | 6 ++++++ sbncode/CAFMaker/FillTrue.h | 3 +++ 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/sbncode/CAFMaker/CAFMaker_module.cc b/sbncode/CAFMaker/CAFMaker_module.cc index 4cc2fcffe..e532328da 100644 --- a/sbncode/CAFMaker/CAFMaker_module.cc +++ b/sbncode/CAFMaker/CAFMaker_module.cc @@ -41,6 +41,7 @@ #endif #include "ifdh_art/IFDHService/IFDH_service.h" +#include "dk2nu/tree/dk2nu.h" // ROOT includes #include "TFile.h" @@ -1469,6 +1470,14 @@ void CAFMaker::produce(art::Event& evt) noexcept { art::fill_ptr_vector(mcfluxes, mcflux_handle); } + art::Handle> dk2nu_handle; + GetByLabelStrict(evt, std::string("generator"), dk2nu_handle); + + std::vector> dk2nus; + if (dk2nu_handle.isValid()) { + art::fill_ptr_vector(dk2nus, dk2nu_handle); + } + // get the MCReco for the fake-reco art::Handle> mctrack_handle; GetByLabelStrict(evt, std::string("mcreco"), mctrack_handle); @@ -1552,9 +1561,13 @@ void CAFMaker::produce(art::Event& evt) noexcept { // holder for invalid MCFlux simb::MCFlux badflux; // default constructor gives nonsense values + // holder for invalid Dk2Nu (default-constructed ancestor vector is empty -- treated as "absent") + bsim::Dk2Nu baddk2nu; + for (size_t i=0; i mctruth, const simb::MCFlux &mcflux, + const bsim::Dk2Nu &dk2nu, const simb::GTruth& gtruth, const std::vector &srparticles, const std::map>> &id_to_truehit_map, @@ -549,6 +552,9 @@ namespace caf { // Set the MCFlux stuff srneutrino.initpdg = mcflux.fntype; srneutrino.baseline = mcflux.fdk2gen + mcflux.fgen2vtx; + srneutrino.dk2gen = mcflux.fdk2gen; + srneutrino.prod_time = (!dk2nu.ancestor.empty()) + ? dk2nu.ancestor.back().startt : std::numeric_limits::signaling_NaN(); srneutrino.parent_pdg = mcflux.fptype; srneutrino.parent_dcy_mode = mcflux.fndecay; srneutrino.prod_vtx.x = mcflux.fvx; diff --git a/sbncode/CAFMaker/FillTrue.h b/sbncode/CAFMaker/FillTrue.h index 419ed6ee9..e7579d799 100644 --- a/sbncode/CAFMaker/FillTrue.h +++ b/sbncode/CAFMaker/FillTrue.h @@ -33,6 +33,8 @@ #include "sbnanaobj/StandardRecord/StandardRecord.h" #include "sbnanaobj/StandardRecord/SRMeVPrtl.h" +namespace bsim { class Dk2Nu; } + namespace caf { struct HitsEnergy { @@ -86,6 +88,7 @@ namespace caf void FillTrueNeutrino(const art::Ptr mctruth, const simb::MCFlux &mcflux, + const bsim::Dk2Nu &dk2nu, const simb::GTruth& gtruth, const std::vector &srparticles, const std::map>> &id_to_truehit_map, From 28cb2b384faa65b95bca5d3aac29bd91ea675e4c Mon Sep 17 00:00:00 2001 From: VCLanNguyen Date: Tue, 29 Sep 2026 16:17:49 -0500 Subject: [PATCH 2/4] Fill MeVPrtl production-time from meson_dpos_beamcoord Companion to the sbnanaobj SRMeVPrtl::prod_time field: sources it from MeVPrtlTruth::meson_dpos_beamcoord.T(), the clean pre-beam-offset meson decay time (already threaded from the BNB flux ntuple's ini_t[0]). Co-Authored-By: Claude Sonnet 5 --- sbncode/CAFMaker/FillTrue.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/sbncode/CAFMaker/FillTrue.cxx b/sbncode/CAFMaker/FillTrue.cxx index 9d291b5fe..8be94a3f6 100644 --- a/sbncode/CAFMaker/FillTrue.cxx +++ b/sbncode/CAFMaker/FillTrue.cxx @@ -387,6 +387,7 @@ namespace caf { srtruth.position.y = truth.decay_pos.Y(); srtruth.position.z = truth.decay_pos.Z(); srtruth.time = truth.decay_pos.T(); + srtruth.prod_time = truth.meson_dpos_beamcoord.T(); //Meson time from flux file. srtruth.momentum.x = truth.mevprtl_mom.X(); srtruth.momentum.y = truth.mevprtl_mom.Y(); From dc6280336e2d1bd88251dc348e200f463547c2ec Mon Sep 17 00:00:00 2001 From: VCLanNguyen Date: Wed, 14 Oct 2026 13:24:29 -0500 Subject: [PATCH 3/4] Address sbncode#675 review comments (ported from gen2) - Fill SRTrueInteraction.baseline/dk2gen natively in cm (util::kMeterToCentimeter) instead of m - Fetch dk2nu via a raw product handle instead of an art::Ptr vector; use fParams.GenLabel() for both the mcflux and dk2nu handle fetches instead of a hardcoded "generator" string - const-qualify the placeholder baddk2nu; de-duplicate the generator_ enum assignment via a local reference Ported from gen2's sbncode#675 review comments -- the underlying code is identical in both trees, even though this thread had no review comments of its own (sbncode#676). CorrectMCTiming() and its lambda/util::kc/Doxygen/debug-print fixes don't apply here -- that function doesn't exist on this branch. Co-Authored-By: Claude Sonnet 5 --- sbncode/CAFMaker/CAFMaker_module.cc | 26 +++++++++++--------------- sbncode/CAFMaker/FillTrue.cxx | 5 +++-- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/sbncode/CAFMaker/CAFMaker_module.cc b/sbncode/CAFMaker/CAFMaker_module.cc index e532328da..9c5fb87c9 100644 --- a/sbncode/CAFMaker/CAFMaker_module.cc +++ b/sbncode/CAFMaker/CAFMaker_module.cc @@ -1463,7 +1463,7 @@ void CAFMaker::produce(art::Event& evt) noexcept { } art::Handle> mcflux_handle; - GetByLabelStrict(evt, std::string("generator"), mcflux_handle); + GetByLabelStrict(evt, fParams.GenLabel(), mcflux_handle); std::vector> mcfluxes; if (mcflux_handle.isValid()) { @@ -1471,12 +1471,10 @@ void CAFMaker::produce(art::Event& evt) noexcept { } art::Handle> dk2nu_handle; - GetByLabelStrict(evt, std::string("generator"), dk2nu_handle); + GetByLabelStrict(evt, fParams.GenLabel(), dk2nu_handle); - std::vector> dk2nus; - if (dk2nu_handle.isValid()) { - art::fill_ptr_vector(dk2nus, dk2nu_handle); - } + std::vector const* dk2nus = + dk2nu_handle.isValid() ? dk2nu_handle.product() : nullptr; // get the MCReco for the fake-reco art::Handle> mctrack_handle; @@ -1562,12 +1560,12 @@ void CAFMaker::produce(art::Event& evt) noexcept { simb::MCFlux badflux; // default constructor gives nonsense values // holder for invalid Dk2Nu (default-constructed ancestor vector is empty -- treated as "absent") - bsim::Dk2Nu baddk2nu; + bsim::Dk2Nu const baddk2nu; for (size_t i=0; iat(i) : baddk2nu; simb::GTruth gtruth; bool ok = GetAssociatedProduct(fmp_gtruth, i, gtruth); @@ -1584,13 +1582,11 @@ void CAFMaker::produce(art::Event& evt) noexcept { FillTrueNeutrino(mctruth, mcflux, dk2nu, gtruth, true_particles, id_to_truehit_map, srtruthbranch.nu.back(), i, fActiveVolumes); - if (ok) { - srtruthbranch.nu.back().generator = caf::kGENIE; - } else if (i < mevprtl_truths.size()) { - srtruthbranch.nu.back().generator = caf::kMeVPrtl; - } else { - srtruthbranch.nu.back().generator = caf::kUnknownGenerator; - } + SRTrueInteraction &nu = srtruthbranch.nu.back(); + caf::generator_ &generator = nu.generator; + if (ok) generator = caf::kGENIE; + else if (i < mevprtl_truths.size()) generator = caf::kMeVPrtl; + else generator = caf::kUnknownGenerator; srtruthbranch.nu.back().genie_evtrec_idx = fGenieEventCounter; diff --git a/sbncode/CAFMaker/FillTrue.cxx b/sbncode/CAFMaker/FillTrue.cxx index 8be94a3f6..043d9f62d 100644 --- a/sbncode/CAFMaker/FillTrue.cxx +++ b/sbncode/CAFMaker/FillTrue.cxx @@ -7,6 +7,7 @@ #include "larcorealg/Geometry/WireReadoutGeom.h" #include "larevt/SpaceCharge/SpaceCharge.h" #include "larcore/CoreUtils/ServiceUtil.h" +#include "larcoreobj/SimpleTypesAndConstants/PhysicalConstants.h" #include "RecoUtils/RecoUtils.h" #include "CLHEP/Random/RandGauss.h" @@ -552,8 +553,8 @@ namespace caf { // Set the MCFlux stuff srneutrino.initpdg = mcflux.fntype; - srneutrino.baseline = mcflux.fdk2gen + mcflux.fgen2vtx; - srneutrino.dk2gen = mcflux.fdk2gen; + srneutrino.baseline = (mcflux.fdk2gen + mcflux.fgen2vtx) * util::kMeterToCentimeter; + srneutrino.dk2gen = mcflux.fdk2gen * util::kMeterToCentimeter; srneutrino.prod_time = (!dk2nu.ancestor.empty()) ? dk2nu.ancestor.back().startt : std::numeric_limits::signaling_NaN(); srneutrino.parent_pdg = mcflux.fptype; From 3f543447c82944649ee6e734f782fb9881d58e05 Mon Sep 17 00:00:00 2001 From: VCLanNguyen Date: Wed, 14 Oct 2026 13:36:11 -0500 Subject: [PATCH 4/4] Fill SRTrueInteraction.prod_time in us, not ns Converts dk2nu's raw ns-valued ancestor startt to us at fill time, matching the README's Time=us convention and the sibling time field's existing ns->us fill pattern. Ported from the gen2 tree, where the same fix also required reworking CorrectMCTiming()'s offset formula (that function doesn't exist on this branch). Co-Authored-By: Claude Sonnet 5 --- sbncode/CAFMaker/FillTrue.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sbncode/CAFMaker/FillTrue.cxx b/sbncode/CAFMaker/FillTrue.cxx index 043d9f62d..3cf135a04 100644 --- a/sbncode/CAFMaker/FillTrue.cxx +++ b/sbncode/CAFMaker/FillTrue.cxx @@ -556,7 +556,7 @@ namespace caf { srneutrino.baseline = (mcflux.fdk2gen + mcflux.fgen2vtx) * util::kMeterToCentimeter; srneutrino.dk2gen = mcflux.fdk2gen * util::kMeterToCentimeter; srneutrino.prod_time = (!dk2nu.ancestor.empty()) - ? dk2nu.ancestor.back().startt : std::numeric_limits::signaling_NaN(); + ? dk2nu.ancestor.back().startt / 1000. /* ns -> us */ : std::numeric_limits::signaling_NaN(); srneutrino.parent_pdg = mcflux.fptype; srneutrino.parent_dcy_mode = mcflux.fndecay; srneutrino.prod_vtx.x = mcflux.fvx;