Repository navigation
KinKal stability knobs to allow bfcorr=true for CentralHelix extrap to CRV - #2021
Conversation
|
Hi @RobMina,
which require these tests: build. @Mu2e/write, @Mu2e/fnalbuild-users have access to CI actions on main. ⌛ The following tests have been triggered for 71a5cc1: build (Build queue - API unavailable) |
|
☔ The build is failing at 71a5cc1.
N.B. These results were obtained from a build of this Pull Request at 71a5cc1 after being merged into the base branch at ff9b517. For more information, please check the job page here. |
oksuzian
left a comment
There was a problem hiding this comment.
PR Review Summary — #2021
Reviewed at head 71a5cc1c. first pass
Decision
- 🟡 comment only
Two things hold this at comment. It cannot build yet: the only blocker is getting the KinKal changes into a build environment, which is a merge-order issue, not a defect in this diff. Two 🟡 items are worth settling before merge. One is about how a misconfiguration fails; the other is an unannounced change to what KKCHmu saves. With both done and a green build, I would approve.
Scope understood
- This is the Offline side of KFTrack/KinKal#224, which merged 2026-09-29 as
dbc9aef7. It adds:bfield.minUsableField, read from the BField geometry file intoBFieldConfigand passed toKinKal::BFieldMapby everyKKBField;- the
MinDomainTimeStepandDomainMarginfit settings; hasTraj()guards on saving in the three fit modules;- a re-check of
goodFitafter CentralHelix extrapolation; - guards in
KKTruthSeedagainst building a helix where the field is unusable.
- Two new BField geometry files,
bfgeom_v01_minfield.txt(1e-6 T) andbfgeom_v01_minfield0p3.txt(0.3 T), each includebfgeom_v01.txt. - All three new settings default to off:
minUsableField0,MinDomainTimeStep0, andDomainMarginnegative, which means unconfined.
Merge prerequisite (not a finding against the diff)
- The build at
71a5cc1cfails, as the PR body says it will. I pulledscons.logfrom build 3410: all 11 compile errors are #224 API calls missing from the environment's KinKal. The missing calls areBFieldMap(double),Config::mindtstep_/domainmargin_,Track::hasTraj,BFieldMap::usableandCentralHelix::constructible. - No KinKal tag contains #224.
v3.7.0(2011f342) is still the newest tag, and #224 is 13 commits after it. So this needs a KinKal release and a Mu2e envset that picks it up. - Until then I don't see a point in re-triggering the build. I'll re-check once the envset is bumped.
Findings
-
🟡 [S2] If
MinDomainTimeStepis larger than the extrapolation'sMaxDtStep,CentralHelixFitsilently produces no tracks instead of failing the job.- Evidence: #224 checks this pair in
Track::extrapolate(Fit/Track.hh:941atdbc9aef7), but only whenbfcorr_is on, and it does so by throwingstd::invalid_argumenton every track. InCentralHelixFit_module.ccthe extrapolation is inside the per-tracktry(:345), whosecatch (std::invalid_argument const&)(:386) prints only ifprint_ > 0.CHXTRAPhasMaxDtStep : 1.0, so the very configuration this PR enables would drop everyKKCHmutrack with no message:bfcorr=truewith anyMinDomainTimeStepabove 1 ns.LoopHelixFitandKinematicLineFithave no such catch, so there the same error stops the job. - Impact: a misconfiguration looks like an empty collection.
KKTruthSeedcopiesexconfig_.mindtstep_onto the truth fit (KKTruthSeed_module.cc:300), so it inherits the same pairing. - Suggested fix: check the pair once, in the module constructors. If
bfieldCorris on andMinDomainTimeStep > ExtrapolationSettings.MaxDtStep, throwcet::exception. The per-event throw in KinKal then becomes unreachable in Mu2e configurations.
- Evidence: #224 checks this pair in
-
🟡 [S2]
CentralHelixFitnow drops tracks whose extrapolation fails. Before this PR it saved them withFitOKcleared. The change is unconditional, and the PR body does not mention it.- Evidence:
CentralHelixFit_module.cc:364-370now recomputesgoodfitafterextrap_->extrapolateand saves only whengoodfit || saveall_. Before,goodfitwas fixed before extrapolation, andKKFit::createSeed(KKFit.hh:678-686) clearedFitOKwhen the status had become unusable. So the track was kept, flagged as not OK.KKCHmuruns in ProductionJobConfig/reco/prolog.fcl(the OffSpillCentralHelixRecosequence), andmdc2025/reco.jsonwrites aCentralHelixOutput. - Impact: in production, cosmic tracks whose tracker fit is fine but whose extrapolation to the CRV fails are now missing entirely. Before, they were present with
FitOKoff. This matches whatKinematicLineFitalready does (:317-320), so it is defensible, but it changes the count of a production collection.LoopHelixFitstill saves after a failed extrapolation (:409-418), so the three modules now differ in how they treat that case. - Suggested fix: add a sentence to the PR description. Ideally, also give the
KKCHmucount before and after on a cosmic sample using the production config (CHDRIFTEXThasBFieldCorrection : false). Alternatively, keep the old behaviour and letFitOKcarry the result.
- Evidence:
-
🟡 [S2] A sentinel value and C++ defaults for fit settings that the rest of the table leaves to the prolog.
- Evidence: in
KKFitSettings.hh:38-39,DomainMargindefaults to-1.0and means "unconfined" (KKFitSettings.cc:26);MinDomainTimeStepdefaults to0.0. Every otherfhicl::Atomin this struct, lines 27-37, has no C++ default and is set inMu2eKinKal/fcl/prolog.fcl. - Impact: a negative number meaning "off" is exactly the case
fhicl::OptionalAtomexists for. A C++ default hides the setting fromfhicl-dumpof the prolog tables. - Suggested fix: make
DomainMarginafhicl::OptionalAtom<double>, so that absent means unconfined and a present value must be ≥ 0 (throw otherwise). Also setMinDomainTimeStep : 0.0in the*SEEDFIT/*EXTprolog tables, asBCorrTolerancealready is.
- Evidence: in
-
🟡 [S2] A reconstruction threshold that lives in the BField geometry file only works for jobs on the field configuration its file includes.
- Evidence:
minUsableFieldis read throughSimpleConfig(BFieldConfigMaker.cc:50), and the only way to set it is a whole new geometry file. Both new files includebfgeom_v01.txtonly. Production jobs also usebfgeom_DSOff.txt(JobConfig/common/Run1B.fcl:12),bfgeom_no_field.txt(cosmic/ExtractedCRY.fcl:11) and the DS50 and DSMap variants. Enabling the protection for any of those means yet another_minfieldcopy of each file. A GitHub code search of the Mu2e organisation finds no consumer of either new file. - The 0.3 T value has no source. The comment says it "trades extrapolation accuracy for stability", but no measurement says how much.
- The 1e-6 T file restates KinKal's
BFieldMap::zeroField().usableFieldalready takesmax(minfield_, zeroField()), so any value up to 1e-6 T behaves identically. - Impact: the threshold multiplies with every field file, and the new files are unused. The rationale for putting it there ("every module in a job shares it") is sound, but a single job-level setting would give the same guarantee without depending on which field file is used.
- Suggested fix: either keep the geometry route but add only the files that a named job config uses, citing where 0.3 T came from; or move the threshold to a single fhicl value shared by the fit modules (a prolog table referenced by each). I don't insist on either; I'd like the choice explained.
- Evidence:
-
⚪ [S3]
scripts/build/SConscriptonly loses its trailing blank line, which is unrelated to this change.KKBFieldnow reachesGeomHandle<BFieldConfig>inside its constructor (KKBField.cc:10). That works, becauseBFieldConfigis registered under the samehasBFieldManagercondition as theBFieldManagerthatKKBFieldalready needs (GeometryService.cc:339-343). PassingBFieldConfig const&in explicitly would make the dependency visible at the six call sites, though.
Verified (🟢)
- 🟢 Existing fits are unchanged apart from finding 2. With
minUsableField_ = 0,BFieldMap::protecting()is false.MinDomainTimeStep = 0is KinKal's own default, and a negativeDomainMarginkeepsdomainmargin_at its unconfinednumeric_limits::max()(Fit/Config.hh:33-34atdbc9aef7). No fcl in Offline, Production ormu2e-trig-configsets any of the three, and no prodtools campaign JSON names the new files. So the default path reads exactly what it read before, other than thegoodFitre-check. - 🟢 It compiles against KinKal at the #224 merge. The seven changed
.ccfiles passg++ -std=c++20 -fsyntax-only -Wall -Wextra -Werror=reorder -Wtype-limits -Wimplicit-fallthrough -Wunused-but-set-parameteron the merge of this PR with current main89bfebf2, with KinKaldbc9aef7headers ahead of the envset copy (museal9-prof-e29-p106). The only warnings are pre-existing-Wunused-parameterones in KinKal andTrackerGeomheaders. This is a syntax check; nothing was linked or run. - 🟢 The
hasTraj()guards close a crash underSaveAllFits : true. A fit that fails before its trajectory exists would have reachedcreateSeed/sampleFitwith a nullfittraj_. The guard is in all three fit modules. Each module'sgoodFitreturns before touchingfitTraj()when the status is unusable, so the ordering is safe. The twoRegrow*modules checkfitStatus().usable()before using the trajectory and need no change. - 🟢
KKTruthSeedguards. Truth pieces are now skipped whereusable(tpos)fails orCentralHelix::constructiblerefuses the state, which #224 now enforces in the constructor. A field-corrected truth fit with no saved reco domains returnsnullopt, the same asRegrowLoopHelix.KKCHmu(CHDriftFit) saves domains (SaveDomains : true), so the domain guard is not hit in the intended setup. The module is MC-diagnostic only, and no Production or trigger fcl instantiates it. - 🟢 Cross-PR interaction: the merge with main
89bfebf2(after #2018) and with open #2020 (KKStrawHit.hhonly) is clean undergit merge-tree. There is no overlapping file.
Validation check
- Build/tests run: FNALbuild fails at this head for the KinKal reason above. My own check was the syntax-only compile listed above.
- Config contract check: partial. No fcl changed. The new keys have C++ defaults (finding 3). The new geometry text files follow the
#includepattern ofbfgeom_DS50_v01.txt; I did not parse them throughSimpleConfig. - Cross-repo consistency: needs follow-up. KinKal#224 is merged, but no KinKal tag or Mu2e envset contains it yet.
Not checked
- No art job. I did not measure how many CentralHelix extrapolations to the CRV succeed with
bfcorr=truewith and without the new settings, nor the change inKKCHmucount from finding 2. The PR gives no numbers either. - Whether 0.3 T is the right handoff threshold for extrapolation to the CRV.
- For the LoopHelix instantiation of
KKTruthSeed, the newusable(tpos)skip drops truth pieces outside the inner maps' bounding boxes. I believe that is intended, since those pieces had a zero field before, but I have not run it.
Author follow-ups
- Say which KinKal tag and envset this needs, and re-trigger the build once it exists.
- Check
MinDomainTimeStepagainst the extrapolationMaxDtStepin the module constructors (finding 1). - State the
KKCHmubehaviour change, and preferably give its count before and after on a cosmic sample (finding 2). DomainMargin→OptionalAtom; prolog values for both new settings (finding 3).- Name the job config that uses each new
bfgeom_*_minfield*file and the source of 0.3 T, or move the threshold to fhicl (finding 4). - Please add validation to the description: a before/after on the fraction of CentralHelix tracks reaching the CRV with
bfcorr=true, which is the point of the PR.
|
Validation (follow-up 6). 112 Run-2 cosmic digi files (98,079 events), CentralHelix fit extrapolated to the
Default path (all settings unset), Offline main vs this PR + KinKal#224, production configs: LoopHelix 20k |
oksuzian
left a comment
There was a problem hiding this comment.
PR Review Summary — #2021
Reviewed at head 1fff0c2f. Re-review of 71a5cc1c.
Decision
- 🟡 comment only
Only one thing holds this at comment: it still cannot build. mu2e/buildtest has not run at 1fff0c2f, and it would fail as build 3410 did. No KinKal tag contains KFTrack/KinKal#224: v3.7.0 (2011f342) is still the newest, and KinKal main is still at the #224 merge dbc9aef7. That is a merge-order point, not a defect in this diff. On the code, what remains open is 🟡/⚪ only. I will approve once a Mu2e envset carries #224 and the build here is green.
What changed since 71a5cc1c
1fff0c2f, "Address AI review comments", adds 33 lines. It addsKKExtrap::checkConfig, called from the constructors of all three fit modules andKKTruthSeed.DomainMarginbecomes afhicl::OptionalAtomthat throws when negative.MinDomainTimeStep : 0.0is set in the prolog tables.- @RobMina posted validation numbers in a comment: 98,079 Run-2 cosmic events, bfcorr on vs off. The default path was compared bit-for-bit against
mainon LoopHelix, CentralHelix and KinematicLine samples.
Prior findings
-
🟢 [was S2 #1]
MinDomainTimeStep>MaxDtStepsilently emptiesKKCHmu— FIXED, verified in the code.KKExtrap::checkConfig(KKExtrap.hh:86-90) throwscet::exceptionat construction whenbfcorr_is on andmindtstep_ > maxdtstep_. EveryExtrapolate*object inKKExtraptakes the samemaxdtstep_, so one comparison covers all targets. It is called inCentralHelixFit(:237),LoopHelixFit(:229),KinematicLineFit(:223) andKKTruthSeed(:149). Each passesexconfig_when there is an extension schedule andconfig_otherwise. That matches whatTrack::config()(config_.back()) holds whenextrapolateruns afterextendTrack.LoopHelixFit's finalization config is a copy ofexconfig_, so it has the samebfcorr_/mindtstep_.- A corner, not a finding: with
SaveAllFits : true, a LoopHelix fit that failsgoodFitis never extended but still reachesextrapolateunderconfig_, while the check testedexconfig_. If onlyconfig_were misconfigured,LoopHelixFithas no catch, so it would stop the job loudly rather than go silent. Checking both configs would close it for one extra line.
- A corner, not a finding: with
-
🟢 [was S2 #2]
CentralHelixFitnow drops tracks whose extrapolation fails — ADDRESSED with evidence. The code is unchanged, but the author reports that CentralHelix output on the default production path (10k events, 527 tracks) is identical tomainat tolerance 0, as is LoopHelix (243) and KinematicLine (478). So thegoodFitre-check does not moveKKCHmuthere. Withbfcorr=true, the reported track count drops 9.1% (57,032 → 51,833), while truth-matched CRV crossings rise 3.1% and the longitudinal core residual shrinks from 407 to 137 mm. Part of that drop is this re-check, and anyone switchingbfcorron should know it. I did not reproduce these numbers. The PR description still does not mention the behaviour change; one sentence there would help the next reader. -
🟢 [was S2 #3]
DomainMarginsentinel and C++ defaults — FIXED.DomainMarginisOptionalAtom<double>. When absent, KinKal's unconfined default stays, and a negative value throws inmakeConfig(KKFitSettings.cc:27-31).MinDomainTimeStep : 0.0is now in all eight fit/extension tables that carryBCorrTolerance(CHSEEDFIT,CHSEEDEXT,CHDRIFTEXT,LHSEEDFIT,KKNOEXT,LHSEEDEXT,LHDRIFTEXT,REGROW). The other fourBCorrTolerancehits are*XTRAPtables of a different struct. The C++ default0.0onminDomainTimeStep(KKFitSettings.hh:39) remains alongside the prolog value. That is harmless; drop it if you want one home. -
🟡 [S2, was S2 #4]
minUsableFieldlives in the BField geometry file — OPEN, unchanged. Bothbfgeom_v01_minfield*.txtfiles are still in the diff, with no consumer in any fcl. The validation usedminUsableField1e-6. That makes sense: any value above 0 is what switches KinKal's protection on (BFieldMap::protecting()), so the 1e-6 file acts as an on/off switch rather than a threshold. The 0.3 T file was not used in the validation and still has no source for the value. Non-gating. Either dropbfgeom_v01_minfield0p3.txtuntil a job needs it, or cite what 0.3 T is based on. -
⚪ [S3, was S3 #5]
scripts/build/SConscriptstill loses its trailing blank line, unrelated to this PR.KKBField's hiddenBFieldConfigdependency is unchanged. Both non-gating.
New at this head
- None beyond the corner noted under finding 1.
Validation check
- Build/tests run: no
mu2e/buildtestat1fff0c2f("not triggered yet"). I did not trigger it, since it cannot pass before the KinKal release. My own check: all seven changed.ccfiles passg++ -std=c++20 -fsyntax-only -Wall -Wextra -Werror=reorder -Wtype-limits -Wimplicit-fallthrough -Wunused-but-set-parameteron the merge of1fff0c2fwith main89bfebf2, against KinKaldbc9aef7headers in museal9-prof-e29-p106. The only warnings are pre-existing-Wunused-parameterones in KinKal headers. - Config contract check: pass.
fhicl-dumpofCHSEEDFIT,CHDRIFTEXT,LHDRIFTEXT,REGROWandKKNOEXTfrom the head prolog resolves, and each showsMinDomainTimeStep: 0. No fcl setsDomainMargin. - Cross-repo consistency: needs a KinKal tag containing #224 and an envset that picks it up.
Not checked
- The author's validation numbers were not reproduced. No art job was run.
- The throw paths of
checkConfigandDomainMargin < 0were read, not exercised.
Author follow-ups
- Name the KinKal tag and envset once they exist, and re-trigger the build then.
- Optional: one sentence in the PR description about the
KKCHmugoodFitre-check (finding 2). - Optional: drop or source
bfgeom_v01_minfield0p3.txt(finding 4).
oksuzian
left a comment
There was a problem hiding this comment.
PR Review Summary — #2021
Reviewed at head 0846afe6cf2c75e110952dba6a44920ad024322b. Re-review of 1fff0c2f.
Decision
- 🟡 comment only
Unchanged from my last review: the code is approvable, and the only hold is that it cannot build yet. No KinKal tag contains KFTrack/KinKal#224. v3.7.0 (2011f342) is still the newest tag, and KinKal main is still the #224 merge dbc9aef7. mu2e/buildtest at this head shows PENDING with no build behind it. I will approve once a Mu2e envset carries #224 and the build here is green.
What changed since 1fff0c2f
0846afe6, "Update doc comment to clarify unbiased DOCA meaning", is a one-line comment change inRecoDataProducts/inc/TrkStrawHitSeed.hh:175. It fixes the typo "unbiaed" and records that_udocais taken from the final fit trajectory, while the hit-state updaters (the ANNs) used the unbiased DOCA from the previous fit cycle.- 🟢 The comment matches the code:
_udocais filled fromuptca.doca()in the main constructor (TrkStrawHitSeed.hh:46). That is the unbiased PTCA passed in when the KalSeed is sampled after the final fit. I did not re-trace which iteration's DOCA the ANN updaters read; I am relying on the comment and the KinKal#226 discussion for that half. - No code, fcl or data-product layout change, so none of the prior findings move.
Prior findings, carried
- 🟢 [was S2]
MinDomainTimeStep>MaxDtStep: fixed at1fff0c2f. The corner withSaveAllFitsonconfig_versusexconfig_remains a note. - 🟢 [was S2]
CentralHelixFitgoodFitre-check: addressed with the author's evidence. A sentence in the PR description is still optional. - 🟢 [was S2]
DomainMarginsentinel: fixed. - 🟡 [S2]
bfgeom_v01_minfield0p3.txthas no consumer and no source for 0.3 T: open, non-gating. - ⚪ [S3]
SConscripttrailing blank line;KKBField's hiddenBFieldConfigdependency: open, non-gating.
Validation check
- Build/tests run: none at this head. My
-fsyntax-onlycheck at1fff0c2fstill applies: this commit changes only a comment. - Config contract: unchanged.
- Cross-repo: needs a KinKal tag containing #224 and an envset that picks it up.
Author follow-ups
- Name the KinKal tag and envset once they exist, and re-trigger the build then.
|
@FNALbuild run build test |
|
⌛ The following tests have been triggered for 0846afe: build (Build queue - API unavailable) |
|
☔ The build is failing at 0846afe.
N.B. These results were obtained from a build of this Pull Request at 0846afe after being merged into the base branch at e6e99ea. For more information, please check the job page here. |
|
@FNALbuild run build test |
|
⌛ The following tests have been triggered for 0846afe: build (Build queue - API unavailable) |
|
☀️ The build tests passed at 0846afe.
N.B. These results were obtained from a build of this Pull Request at 0846afe after being merged into the base branch at 395c773. For more information, please check the job page here. |
This is the followup to a KinKal PR: KFTrack/KinKal#224
Note this will fail to build until the Offline build environment is updated with the KinKal changes from the PR linked above.
This PR includes the Offline side configuration changes that are necessary to allow CentralHelix extrapolation to the CRV with bfcorr=true.