Skip to content

Fix pathological alignment of dead modules for CVH - #47

Open
davidwalter2 wants to merge 3 commits into
WMass:WmassNanoProd_10_6_26from
davidwalter2:WmassNanoProd_10_6_26_CVHFixes
Open

Fix pathological alignment of dead modules for CVH #47
davidwalter2 wants to merge 3 commits into
WMass:WmassNanoProd_10_6_26from
davidwalter2:WmassNanoProd_10_6_26_CVHFixes

Conversation

@davidwalter2

@davidwalter2 davidwalter2 commented Jul 23, 2026

Copy link
Copy Markdown

Motivation

The data/MC comparison of the CVH refit efficiency (Z→μμ, pT 25–65 GeV) shows two localized regions where data is less efficient than MC, both absent in MC because MC uses the ideal geometry. Both trace back to the same origin: modules that were off during data-taking collect no hits, so their alignment DOF are unconstrained and the persisted constants can be arbitrary. The garbage constants then break the Geant4e propagation of the CVH refit for tracks crossing those modules — the muons themselves are perfectly reconstructed by standard tracking (full hit complement, high purity); only the refit aborts.

Hotspot 1 Hotspot 2
location η ∈ [0.1, 0.65], φ ∈ [0.80, 1.00] η ≈ −1.6, φ ≈ −1.05
effect up to 41% efficiency loss 3.2% refit-failure rate (vs 0.13% baseline)
module TIB glued 369141860, mono face 369141862 TID glued 402666796, r-φ face 402666798
pathology face tilted 0.75 rad face translated 1.3 cm (5.4 mm out of its own module plane)

Both pathological modules turn out to be faces of glued pairs whose partner is sane, which is what the final design exploits.

What this PR does

Detection

Two independent flags per module, both untracked parameters with a default, 1e9 = off:

  • orientation — aligned-vs-ideal tilt above gluedGarbageTiltThreshold (default 50 mrad; genuine corrections are < 1 mrad, the pathological one is 0.75 rad).
  • translation — deviation from the local consensus, i.e. the median aligned-vs-ideal displacement of same-layer neighbours (|Δz| < 15 cm, |Δφ| < 0.6), above moduleGarbageShiftThreshold (default 4 mm).

A plain aligned-vs-ideal position cut cannot separate garbage translations from legitimate coherent large-structure movements (up to ~1 cm), hence the consensus. Relative to it, genuine module-level misalignment is sub-mm over the whole tracker (p50 = 0.29 mm, p99 = 1.3 mm, p99.9 = 2.0 mm of 16588 det units), and exactly six modules exceed 4 mm in the 2016 UL alignment: 402666798 (the only one inside the muon acceptance) plus five dead FPix edge modules at |η| ≈ 2.7–2.8. Exactly one composite exceeds the tilt threshold: 369141860.

A glued-pair-local criterion was considered as a simpler discriminator and does not work: over the 3288 glued pairs, |disp_mono − disp_stereo| has p99.9 = 1.6 mm and a largest genuine value of 2.1 mm, against 5.5 mm for the garbage face — no clean separation. The consensus scan is needed anyway, since 5 of the 6 translation outliers are pixel endcap modules with no glued partner at all.

Repair

The two faces of a glued module are a single rigid body, so a sane face determines both the bad face and the composite plane exactly. Both guards therefore share one repair path: when exactly one face of a glued module is flagged (by either criterion), the bad face and the composite are rebuilt as

anchor_aligned ∘ anchor_ideal⁻¹ ∘ (ideal surface)

with the sane face as anchor. Composite↔face relative position, orientation and the Rglued Jacobian then take their ideal values by construction, which is what the downstream plane reconstruction and the alignment parameter mapping assume.

Ideal surface + consensus displacement (with ideal orientation) survives only as the fallback for modules with no local reference: non-glued modules, and the so-far-unobserved case of both faces bad.

Hit ordering

The mono/stereo inner/outer decision for a split matched invalid hit read the raw alignment constants. Since 402666798 sits 5.4 mm out of its module plane — more than the physical face separation — that dot product came out with the wrong sign, and the two dead-channel placeholder hits were emitted back-to-front relative to the surfaces the fit then uses, which the forward-only propagation cannot traverse. Both producers now take those positions from surfacemapD_, the surfaces the fit actually uses.

Applied in both the single-track and two-track producers. Both guards are automatically inert on MC (useIdealGeometry → zero displacements).

Validation

Run2016G Charmonium ALCARECO, 20k events, aligned geometry, single-track producer:

propagation aborts on 369141862 on 402666798
guards off 41 31 9
guards on 1 0 0

The single remaining abort is on FPix 352467464, which neither guard flags — a separate, pre-existing case.

Geometry-level closure, composite vs its sane face, in the sane face's frame:

402666796 369141860
uncorrected 2.5 mm out-of-plane 0.8 mm, + 0.75 rad face rotation
ideal + consensus, ideal orientation 0.57 mm, 2.7 mrad 0.41 mm, 1.6 mrad
anchored on the sane face 0, exact 0, exact

Run2016G SingleMuon, 6 files, 40k events (earlier iteration of the guards, hotspot-2 focused):

  • Hotspot-2 refit failures 17 → 7 = the level of the mirror-η control cell (4); all 10 failures on 402666798 gone
  • +10 recovered tracks in the cell, healthy (16 valid hits, pT ≈ 42 GeV)
  • All other tracks: 50 812 matched, 99.78% bit-identical momentum; the remainder cross repaired modules, |Δ(q/p)| ≲ 10⁻⁵ at p99.9
  • The re-included "hit" is the dead-channel placeholder — the hit-type census confirms the r-φ face was recorded inactive by the conditions data (its stereo partner is alive with normal hit rate), so no measurement ever existed

Notes

  • With these two guards, and no other module deviating by more than 3.3 mm inside the muon acceptance, hotspots 1+2 are the only alignment-induced CVH efficiency holes in the 2016 data.
  • The effect on the analysis appears only at the next reprocessing; for the current dataset the measured data→MC efficiency SF stands.
  • In the CMSSW 15 workflow with the global material model, skipHitlessSurfaces removes the hotspot-2 class by construction (dead-module placeholders are never propagation targets); the guards remain complementary there for garbage constants on modules with valid hits.
  • The corrupted constants themselves (in particular 402666798, −1.3 cm in z) should be reported to tracker alignment.

Review history

Josh asked whether the translation guard fires for glued modules at all, noted that if it does then rebuilding the composite at ideal position + consensus displacement is not right, and asked that the composite be tied to the good side instead — since the composite must keep defined position/orientation relations to the two sides or other alignment logic breaks. The third commit answers that: it does fire for one glued module, the composite is now anchored on the sane face by the same rule as the tilt guard, and the two separate composite rebuilds collapse into one. Fixing the split-hit ordering at its source then made reorderGarbageShiftHits provably the identity (9 calls over 20k events, all on 402666798, no permutation in any of them), so it was removed together with garbageShiftModules_, the garbageShiftReorderHits policy and the drop branch — the per-track hit loop no longer touches a hash set. Net for that commit: 182 insertions, 218 deletions.

🤖 Generated with Claude Code

davidwalter2 and others added 3 commits July 23, 2026 16:23
… modules

Modules that were off during data-taking collect no hits, so their
alignment is unconstrained and the persisted constants can be arbitrary.
Observed in the 2016 alignment: TIB glued module 369141860 has its rphi
face rotated ~49 deg against its partner (ideal: exactly anti-parallel),
which contaminates the composite frame used to anchor the glued-surface
reconstruction and turns the module into a propagation booby trap (the
dominant source of the runaway-leg fit failures).

If the aligned composite orientation deviates from the ideal one by more
than 50 mrad -- far beyond any genuine alignment correction -- rebuild
the composite frame anchored on the component face with the smaller
aligned-vs-ideal tilt, composed with the ideal component->composite
transform, and emit a LogWarning. In the 2016 UL alignment this fires
for exactly one module (369141860: mono tilt 0.752, stereo 0.0016);
with the repair, 8 of the 11 hotspot candidate fits succeed even with
legacy forward-only propagation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EXjsuBb3HHCTK8L1jBx75j
Translation analogue of the glued-tilt (eb96cae) guard. Modules that were
off during data-taking have unconstrained alignment DOF; besides garbage
rotations, the stored constants can carry cm-scale translations (observed:
TID r-phi face 402666798 z-shifted 1.3 cm, 5.3 mm out of its own disk plane,
rank cms-sw#5 outlier of 16588 modules; genuine module-level misalignment relative
to neighbors is sub-mm, p99.9 = 2.0 mm). The mis-placed surface makes the
Geant4e propagation abort for every track carrying the module's dead-channel
placeholder, producing a 3.2% data-only refit-failure hole at eta -1.6,
phi -1.05 (hotspot 2 of the data/MC efficiency comparison).

Detection at geometry load: per-module aligned-vs-ideal displacement compared
with the local consensus (median displacement of same-layer neighbors within
|dz| < 15 cm, |dphi| < 0.6); flag if the deviation exceeds
moduleGarbageShiftThreshold (untracked, default 0.4 cm; 1e9 = off). Repair:
surface rebuilt at ideal position + consensus displacement with ideal
orientation (glued composite as well -- it is half-contaminated by a garbage
face), and hits on flagged modules either re-inserted at the path position
implied by the repaired surface (garbageShiftReorderHits, default true) or
dropped. Re-ordering is required when keeping the hit: the stored hit order
follows the garbage constants and the repaired surface can sit behind its
neighbor, which the forward-only propagation cannot traverse. Inert on MC
(ideal geometry gives zero displacements).

Also adds CVHDIAG failure diagnostics at the three data failure points
(propagation abort, hit-update failure, GN divergence) printing the failing
surface and track kinematics.

Validated on Run2016G SingleMuon data (6 files, 40k events): hotspot refit
failures 17 -> 7 (= mirror-cell level), all 10 failures on 402666798 gone,
+10 recovered healthy tracks, 99.78% of the remaining tracks bit-identical;
drop and reorder policies give identical momenta (the re-included hit is the
dead-channel placeholder -- no measurement existed).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01992a1iMkSNB6fRiAA3BbAj
Review follow-up (Josh): the translation guard does fire for a glued
module -- 402666798 is the r-phi face of glued pair 402666796 (the other
five outliers are pixel endcap, which have no glued partner at all) --
so rebuilding the composite at ideal position + consensus displacement
with ideal orientation was the wrong thing to do there.

The two faces of a glued module are one rigid body, so a sane face fixes
both the bad face and the composite exactly. Both guards now share a
single repair: when exactly one face is bad -- by tilt vs ideal or by
deviation from the layer consensus -- the bad face and the composite
plane are rebuilt as anchor_aligned o anchor_ideal^-1 applied to their
ideal surfaces. Composite<->face position, orientation and Rglued then
take their ideal values by construction, so the plane reconstruction and
the alignment parameter mapping see a consistent composite. The old
composite rebuild left 402666796 0.57 mm and 2.7 mrad away from that
relation (uncorrected: 2.5 mm out-of-plane). The tilt guard previously
repaired only the composite, leaving the bad face's in-plane DOF taken
from the garbage constants (369141862: 2.1 mm displaced plus the 0.75 rad
rotation of its local axes); those are now anchored too.

Ideal surface + consensus displacement survives only as the fallback for
modules with no local reference: non-glued modules, and the so far
unobserved case of both faces bad. Detection is unchanged -- the
consensus is still needed, since 5 of 6 translation outliers are pixel
endcap, and a glued-pair-local criterion does not separate (2016
geometry: |disp_mono - disp_stereo| p99.9 = 1.6 mm, largest genuine
2.1 mm, against 5.5 mm for the garbage face).

Also fixes the root cause of the hit re-ordering. The mono/stereo
inner/outer decision for a split matched invalid hit read the raw
alignment constants; since 402666798 sits 5.4 mm out of its module plane,
more than the face separation, the dot product came out with the wrong
sign and the two placeholder hits were emitted back-to-front w.r.t. the
surfaces the fit uses. Both producers now take those positions from
surfacemapD_. With that, reorderGarbageShiftHits is the identity: over
20k Run2016G events it fired on 9 tracks, all on 402666798, changed=0
every time. Removed it, along with garbageShiftModules_, the
garbageShiftReorderHits policy and the drop branch -- the per-track hit
loop no longer touches a hash set.

Validation (Run2016G Charmonium ALCARECO, 20k events, aligned geometry):
propagation aborts 41 (guards off) -> 1 (guards on), the remaining one on
FPix 352467464, which neither guard flags. Identical failure count before
and after removing the re-ordering.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant