Skip to content

Mu2eKinKal: fix defects found by a static sweep of the package - #1955

Open
oksuzian wants to merge 1 commit into
Mu2e:mainfrom
oksuzian:fix/mu2ekinkal-static-sweep
Open

Mu2eKinKal: fix defects found by a static sweep of the package#1955
oksuzian wants to merge 1 commit into
Mu2e:mainfrom
oksuzian:fix/mu2ekinkal-static-sweep

Conversation

@oksuzian

Copy link
Copy Markdown
Collaborator

Six defects found by a static review of Mu2eKinKal at 0ef02a66d. All six are mechanical fixes with an existing in-package precedent; none changes fit acceptance or any tuning constant. I have not built this locally — relying on mu2e/buildtest.

1. RegrowKinematicLine indexes a flat KalSeedMCAssns with a collection-local counter

RegrowKinematicLine_module.cc:249 did (*ksmca_H)[iseed], where iseed counts position within this module's own input KalSeedCollection (wired to KKLine).

KalSeedMCAssns is one flat product: CommonMC/src/SelectRecoMC_module.cc:170 does a single produces<KalSeedMCAssns>(), and :468-498 runs one loop over getMany<KalSeedCollection> calling addSingle once per seed per collection. Production/JobConfig/recoMC/prolog.fcl:32 orders them ["KKDe","KKDmu","KKUe","KKUmu","KKLine","KKCHmu"]KKLine is 5th of 6. So on any event with a seed in an earlier collection, (*ksmca_H)[0] for the first KKLine seed returns a KKDe entry, the ptr self-check fails, and the art job dies with cet::exception("Reco").

The sibling RegrowLoopHelix (:305-317) does an art::Ptr-equality search, correct at any offset — which is also why the bug is invisible there: RegrowLH targets KKDe, index 0.

Fixed with a KalSeed -> KalSeedMC map built once per event, which is correct at any offset and also drops the sibling's O(N·M) scan.

2. RegrowLoopHelix: mandatory MustRegrow is absent from the live job config

RegrowLoopHelix_module.cc:98 declared a two-argument fhicl::Atom<std::string> — mandatory, unlike debug at :86 in the same struct.

No job config supplies it. Production/JobConfig/reco/regrowLH.fcl:34-55 builds physics.producers.RegrowLH as a literal block rather than pulling @table::Mu2eKinKal.RegrowLH, and Production/JobConfig/reco/prolog.fcl:122-140 omits it too. The only MustRegrow : "None" in the tree is Mu2eKinKal/fcl/prolog.fcl:642, in the table neither Production block references — grep -rn MustRegrow Production/ returns nothing. Validation fails before the module is constructed, so the constructor's own value check at :200-207 is never reached.

Fixed by giving the Atom the "None" default that table already implies. (The alternative — adding the key to Production — would need a companion PR there; this way the module is correct on its own.)

3. BkgANNSHU: unguarded sqrt(docaVar()) feeds NaN to the MVA

BkgANNSHU.cc:30 was pars[2] = sqrt(tpdata.docaVar());. A non-positive docaVar gives NaN; NaN < mvacut_ is false under IEEE-754, so the else branch runs and the hit is left active — or, if it was inactive, re-activated at :45.

Three sibling call sites clamp the identical quantity: DriftANNSHU.cc:44, CADSHU.cc:31, KKFit.hh:510,567. Adopted the same clamp.

4. KKFit::createSeed dereferences rbegin() of a possibly-empty domain set

KKFit.hh:796 did (*(kktrk.domains().rbegin()))->end() under savedomains_. domains() is a std::set, empty whenever the fit ran without BField correction; rbegin() then equals rend() and dereferencing it is UB.

No committed config triggers it today — but only because Mu2eKinKal/fcl/prolog.fcl:606-608 carries a hand-written comment telling the next author not to set SaveDomains:true there, citing this exact SIGSEGV. Replaced the load-bearing comment with a named cet::exception, and updated the comment to say what now happens.

5. StrawHitUpdaters::name() indexes with a negative enumerator

unknown = -1 (StrawHitUpdaters.hh:12), and name() did names_[static_cast<size_t>(alg)] — UB whenever an unknown state is printed at diag > 1. Bounds-checked; returns "unknown".

6. KLSeedFit omits the mandatory SaveTrajectory key

KKFIT deliberately does not set SaveTrajectory, and every producer that builds from it supplies its own — verified at LHSeedFit:468, LHDriftFit:490, KLDriftFit:531, CHSeedFit:547, CHDriftFit:562, KLTruthSeed:587, CHTruthSeed:606, RegrowLH:636. KLSeedFit did not, so its table cannot pass validation the moment it is added to a path. Added SaveTrajectory : T0, matching CHSeedFit, whose FitSettings and ExtensionSettings KLSeedFit already shares.


Validation

  • Build: not run locally. Every claim above is static — read from the source, Production and mu2e-trig-config, plus grep. Please let buildtest be the arbiter.
  • No art job was run, so Update README.md #1 and Add diagnostics #2 are predicted failures, not observed ones. The cheapest check is one mu2e -c Production/JobConfig/reco/regrowKL.fcl and one regrowLH.fcl over a few events; if either already runs green today, the corresponding finding is wrong and I will withdraw it.
  • No fhicl-dump -a provenance was produced. Add diagnostics #2 and Adjust parameters for new production #6 rest on reading the prologs and grepping @table:: references; a resolution path I failed to model would change them.
  • Scope held deliberately narrow. The sweep also raised items that change fit acceptance or physics and are not in this PR — KinematicLineFit::goodFit() returning only fitStatus().usable() while both siblings also require inDetector()/charge/helicity; KKBField::fieldGrad() returning the transpose of its own documented dB_i/dx_j convention; and ExtrapolateCRVRegion's short-piece fallback being backward-only. Those need an author decision, so I left them out. Happy to open an issue with the full list.

RegrowKinematicLine indexed KalSeedMCAssns with a counter local to its own
input KalSeedCollection. That product is a single flat Assns spanning every
collection SelectRecoMC was configured with (KKDe, KKDmu, KKUe, KKUmu, KKLine,
KKCHmu), so for KKLine the index is wrong whenever an earlier collection has
seeds, and the ptr self-check throws. Replace the positional lookup with a
KalSeed -> KalSeedMC map built once per event; this also removes the O(N*M)
scan the sibling RegrowLoopHelix does.

RegrowLoopHelix declared MustRegrow as a mandatory fhicl::Atom, but no job
config supplies it: Production/JobConfig/reco/regrowLH.fcl builds the producer
block literally instead of pulling @table::Mu2eKinKal.RegrowLH, which is the
only place the key is set. Give the Atom the "None" default that table implies,
so validation no longer fails before the module is constructed.

BkgANNSHU passed sqrt(docaVar()) to the MVA unclamped. A non-positive docaVar
gives NaN, and NaN < mvacut_ is false, so an unscoreable hit is left active or
re-activated. DriftANNSHU, CADSHU and KKFit all clamp the same quantity; do the
same here.

KKFit::createSeed dereferenced rbegin() of the domain set when SaveDomains is
set. That set is empty whenever the fit ran without BField correction, making
this undefined behaviour. Throw a named exception instead; the CHTruthSeed
prolog comment that documented the crash is updated to match.

StrawHitUpdaters::name() indexed names_ with the enumerator value, but
'unknown' is -1, so printing that state at diag > 1 was undefined behaviour.
Bounds-check and return "unknown".

KLSeedFit took KKFitSettings straight from KKFIT, which deliberately does not
set the mandatory SaveTrajectory key. Every sibling supplies its own; add T0 to
match CHSeedFit, whose fit and extension settings KLSeedFit already shares.

Found by a static review of the package at 0ef02a6. Not built locally --
relying on CI for the build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@FNALbuild

Copy link
Copy Markdown
Collaborator

Hi @oksuzian,
You have proposed changes to files in these packages:

  • Mu2eKinKal

which require these tests: build.

@Mu2e/fnalbuild-users, @Mu2e/write have access to CI actions on main.

⌛ The following tests have been triggered for 87d7c03: build (Build queue - API unavailable)

About FNALbuild. Code review on Mu2e/Offline.

@FNALbuild

Copy link
Copy Markdown
Collaborator

☀️ The build tests passed at 87d7c03.

Test Result Details
test with Command did not list any other PRs to include
merge Merged 87d7c03 at 0ef02a6
build (prof) Log file. Build time: 04 min 31 sec
ceSimReco Log file.
g4test_03MT Log file.
transportOnly Log file.
POT Log file.
g4study Log file.
cosmicSimReco Log file.
cosmicOffSpill Log file.
ceSteps Log file.
ceDigi Log file.
muDauSteps Log file.
ceMix Log file.
rootOverlaps Log file.
g4surfaceCheck Log file.
trigger Log file. Return Code 1.
check_cmake Log file.
FIXME, TODO ➡️ TODO (14) FIXME (4) in 5 files
clang-tidy ➡️ 4 errors 48 warnings
whitespace check no whitespace errors found

N.B. These results were obtained from a build of this Pull Request at 87d7c03 after being merged into the base branch at 0ef02a6.

For more information, please check the job page here.
Build artifacts are deleted after 5 days. If this is not desired, select Keep this build forever on the job page.

Comment thread Mu2eKinKal/inc/KKFit.hh
// SaveDomains with a fit that ran without BField correction leaves no domains at all;
// rbegin() would then be rend() and dereferencing it is undefined behaviour
if(kktrk.domains().empty())throw cet::exception("RECO")
<< "mu2e::KKFit: SaveDomains is set but the fit has no BField domains; set BFieldCorrection or SaveDomains:false" << std::endl;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be a warning and a clean return (with empty domains collection) rather than an exception. An uncaught exception would abort the entire art job.

@RobMina

RobMina commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

I encountered an exception when running Production/JobConfig/reco/regrow_kl.fcl, but not the "wrong KalSeed ptr" exception addressed in this PR. Instead, it was "Invalid Time Range" in KinKal::TimeRange constructor:
#1 0x00007ffff214af99 in KinKal::TimeRange::TimeRange (this=this@entry=0x7fffffff4e60, begin=, end=end@entry=11456.136692011529, ordered=true) at /cvmfs/mu2e.opensciencegrid.org/spackages/241207/spack/var/spack/environments/muse-al9-prof-e29-p106/.spack-env/view/include/KinKal/General/TimeRange.hh:17
#2 0x00007ffff2197f41 in mu2e::KKExtrap::toTrackerPerimeterKinKal::KinematicLine(mu2e::KKTrackKinKal::KinematicLine&) const::{lambda(KinKal::TimeDir)#1}::operator()(KinKal::TimeDir) const (__closure=__closure@entry=0x7fffffff50b0, tdir=, tdir@entry=KinKal::TimeDir::backwards) at /cvmfs/mu2e.opensciencegrid.org/spackages/241207/spack/var/spack/environments/muse-al9-prof-e29-p106/.spack-env/view/include/KinKal/General/TimeRange.hh:23
#3 0x00007ffff219858f in mu2e::KKExtrap::toTrackerPerimeterKinKal::KinematicLine (this=this@entry=0xde9650, ktrk=...) at ./Offline/Mu2eKinKal/inc/KKExtrap.hh:174
#4 0x00007ffff21c465b in mu2e::KKExtrap::extrapolateKinKal::KinematicLine (this=0xde9650, ktrk=...) at ./Offline/Mu2eKinKal/inc/KKExtrap.hh:89
#5 0x00007ffff215b030 in mu2e::RegrowKinematicLine::produce (this=0xde4680, event=...) at Offline/Mu2eKinKal/src/RegrowKinematicLine_module.cc:239

The Offline call is in toTrackerPerimeter here:

TimeRange(tref,ftraj.range().end()) : TimeRange(ftraj.range().begin(),tref);

The failure is unrelated to the suggested fix in this PR, but it hides any actual problem that this PR would fix.

A cheap fix would be TimeRange(ftraj.range().begin(), tref, false). Maybe that should be added to this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants