Skip to content

Initialize TrkFilters members that FHiCL can leave unset - #1971

Open
oksuzian wants to merge 1 commit into
Mu2e:mainfrom
oksuzian:fix/trkfilters-uninitialized-cuts
Open

Initialize TrkFilters members that FHiCL can leave unset#1971
oksuzian wants to merge 1 commit into
Mu2e:mainfrom
oksuzian:fix/trkfilters-uninitialized-cuts

Conversation

@oksuzian

@oksuzian oksuzian commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

Intent

Two uninitialized-member reads in TrkFilters, both sourced from FHiCL and neither caught by validation.

fhicl::OptionalAtom<T>::operator()(T& value) assigns only when the key is present and leaves value untouched otherwise (fhiclcpp/types/OptionalAtom.h:44-51). HelixFilter's HelixCutsTool fills fifteen cut thresholds through that form — _hascc, _doHelicityCheck, _hel, _minnstrawhits, _minHitRatio, _minmom, _maxmom, _minpT, _maxchi2XY, _maxchi2PhiZ, _maxd0, _mind0, _maxlambda, _minlambda, _maxnloops, _minnloops — with no in-class initializer and no entry in the constructor's initializer list, and then reads every one of them in the cut chain. Omitting a key from a menu therefore produces a silently wrong trigger rather than a configuration error. _slopeSigMin/_slopeSigMax in the same struct already do it correctly, by keeping the boolean return in _useSlopeSigMin/_useSlopeSigMax and guarding the comparison.

MultiHelixFilter declares a doHistograms parameter and a _doHistograms member but never assigns one from the other, so beginJob and filter decide whether to book and fill histograms by reading an uninitialized bool, and the configuration key does nothing.

Scope

Each threshold gets an in-class initializer chosen so that an unconfigured cut is a no-op, _myTracker gets nullptr, _doHistograms is initialized from the configuration, and _hists defaults to null pointers. _maxpT is deleted rather than initialized — it is declared and never read anywhere in the file.

No committed configuration changes behaviour. All twenty HelixFilter instances in mu2e-trig-config (trigTprFilters.fcl, trigAprFilters.fcl, trigCprFilters.fcl, trigMprFilters.fcl), after expanding their @table:: references, set all fifteen keys; MultiHelixFilter has no consumer in Offline, Production or mu2e-trig-config.

Deliberately not in this PR

These came out of the same read-through and are each a separate topic:

  • Making the fifteen keys required fhicl::Atoms instead of initialized OptionalAtoms. That is the stronger fix — an omitted cut would fail validation instead of silently disabling itself — and every committed instance would still validate. Happy to do that instead if the maintainers prefer it; it is a schema change, so it did not belong in the same commit.
  • prescaleUsingD0Phi and prescalerPar are independent FHiCL entries, so enabling the flag without an amplitude leaves PhiPrescalingParams at its default of zero, evalIPAPresc returns 0, and NEvt % prescaler divides by zero. The one live user sets amplitude: 6.2, whose minimum over phase is exactly 1.0, so nothing crashes today. The fix is an OptionalTable so the pair validates as a unit.
  • HelixFilter converts curvature to momentum with a bare 3./10. and computes _bz0 in beginRun without ever reading it, while MultiHelixFilter multiplies by _bz0. The two modules disagree by a factor of Bz, and the live thresholds are tuned against HelixFilter's current scale, so correcting it shifts every momentum cut in the menu.
  • The maxDt0 timing cut is evaluated over the whole input collection rather than the helices that passed the selection. It is set in no committed configuration.
  • beginJob/beginRun in both modules are virtual without override, which is what would have caught _hists never being booked at compile time.

Validation

Compile and test coverage from CI only — I have not run an art job. The change is behaviour-preserving for every committed configuration, as described above.

fhicl::OptionalAtom<T>::operator()(T&) assigns only when the key is
present and leaves its target untouched otherwise.  HelixCutsTool fills
fifteen cut thresholds through that form with no in-class initializer
and no entry in the constructor's initializer list, so omitting a key
from a HelixFilter configuration makes checkHelix() compare against an
indeterminate value instead of failing validation.  Give each one an
initializer chosen so that an unconfigured cut is a no-op, and
initialize _myTracker to nullptr.  _maxpT, which was never read, is
removed rather than initialized.

MultiHelixFilter never assigned _doHistograms from its own
doHistograms parameter, so the switch that books the histograms in
beginJob and fills them in filter() read an uninitialized bool and the
configuration key had no effect.  Initialize it from the configuration
and default the _hists pointers to nullptr.

No committed configuration changes behaviour: all twenty HelixFilter
instances in mu2e-trig-config set all fifteen keys.

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:

  • TrkFilters

which require these tests: build.

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

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

About FNALbuild. Code review on Mu2e/Offline.

@FNALbuild

Copy link
Copy Markdown
Collaborator

☀️ The build tests passed at b5d26c1.

Test Result Details
test with Command did not list any other PRs to include
merge Merged b5d26c1 at c4b2bc6
build (prof) Log file. Build time: 04 min 22 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 (0) FIXME (1) in 2 files
clang-tidy ➡️ 4 errors 104 warnings
whitespace check no whitespace errors found

N.B. These results were obtained from a build of this Pull Request at b5d26c1 after being merged into the base branch at c4b2bc6.

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.

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.

2 participants