Skip to content

Calorimeter alignment condition support - #1916

Open
bechenard wants to merge 1 commit into
Mu2e:mainfrom
bechenard:alignDB
Open

Calorimeter alignment condition support#1916
bechenard wants to merge 1 commit into
Mu2e:mainfrom
bechenard:alignDB

Conversation

@bechenard

Copy link
Copy Markdown
Contributor

Support for calorimeter alignment via the condition service. Only disk movement and rotations are supported at this point. Code to move the crystals, should this be necessary (I doubt it because we already use their measured placement in the calorimeter and these crystals won't budge without explosives), is readily available. The resulting object is called alignedCalorimeter, following the tracker.

@FNALbuild

Copy link
Copy Markdown
Collaborator

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

  • DbTables
  • CaloConfig
  • ProditionsService
  • CaloCluster
  • CaloConditions

which require these tests: build.

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

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

About FNALbuild. Code review on Mu2e/Offline.

@bechenard bechenard changed the title Calorimete ralignment support Calorimeter alignment contition support Aug 4, 2026
@FNALbuild

Copy link
Copy Markdown
Collaborator

☀️ The build tests passed at 2b0f3ed.

Test Result Details
test with Command did not list any other PRs to include
merge Merged 2b0f3ed at f408474
build (prof) Log file. Build time: 04 min 24 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.
check_cmake Log file.
FIXME, TODO TODO (0) FIXME (0) in 10 files
clang-tidy ➡️ 6 errors 33 warnings
whitespace check no whitespace errors found

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

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.

@oksuzian
oksuzian requested a review from rlcee August 4, 2026 02:37
@bechenard bechenard changed the title Calorimeter alignment contition support Calorimeter alignment condition support Aug 4, 2026

@oksuzian oksuzian left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

PR Review Summary — "Calorimeter alignment condition support" (#1916)

Reviewed at head 2b0f3eda (2026-08-04). 17 files, +464/−14: new CalAlignDisk/CalAlignCrystal DB tables, an alignedCalorimeter proditions entity (deep-copied DiskCalorimeter with disk shifts/rotations applied), and CaloClusterMaker switched from GeomHandle to ProditionsHandle<Calorimeter>. The core design is sound and the dangerous part — mutating a copy of the geometry through const_cast — is verified safe below. The blockers are all in the build/wiring layer, and two of the three are invisible to the scons CI by construction.

Decision

  • 🔴 Request changes. One S0 (CMake configure breaks on merge) and three S1s (fromDb ignores its own params, missing factory registration, CMake link deps not updated). All are small fixes.

Scope understood

  • Rigid-body disk alignment (dx,dy,dz,rx,ry,rz) from fcl file or DB, applied to a deep copy of the GeomHandle DiskCalorimeter, served as proditions entity Calorimeter ("alignedCalorimeter" in config).
  • Crystal-level alignment plumbed but deliberately zeroed ("won't budge without explosives"); only CaloClusterMaker consumes the aligned geometry so far.

Findings

1. 🔴 [S0] CMake configure fails: both new configure_file inputs do not exist — the spack/CMake build of Offline breaks on merge, and scons CI cannot see it.

  • Evidence: CaloConditions/CMakeLists.txt adds configure_file(...data/crystal_align.dat ...) and configure_file(...data/disk_nominal.dat → data/disk_align.dat). CaloConditions/data/ at this head contains Sim_crystal.txt, caloDMAP_nominal.dat, disk_align.txt, nominal.txt — neither crystal_align.dat nor disk_nominal.dat exists. configure_file with a missing input is a hard configure-time error. The Jenkins buildtest is scons-only and green.
  • Impact: identical failure mode to the crystalPos.txt incident (#1908 → spack break → #1914), caught pre-merge this time.
  • Suggested fix: delete both lines. install(DIRECTORY data ...) is already present in this CMakeLists and covers the install; the configure_file(${CURRENT_BINARY_DIR}) staging idiom is exactly what #1914 removed from CalorimeterGeom — don't extend it. (The mismatched output name disk_nominal.dat → disk_align.dat in the second line is a symptom of the same copy-paste.) The runtime path is safe without them: the fcl name Offline/CaloConditions/data/disk_align.txt resolves via ConfigFileLookupPolicy from the source tree or the installed share/.

2. 🟠 [S1] fromDb computes validated parameter vectors and then ignores them — raw DB crystal rows get applied, contradicting the PR's own scope.

  • Evidence: AlignedCalorimeterMaker.cc::fromDb builds disk_align_params via readDb(...) (range+count validation) and a zeroed crystal_align_params, then calls alignCalorimeter(ptr, cad_p->rows(), cac_p->rows()) — both locals discarded.
  • Impact: for disks it's dead work (table addRow already enforces sequential indices, so contents are identical). For crystals it's a behavior contradiction: fromFcl forces zeros per the stated "crystals won't budge" scope, but fromDb applies whatever cal.aligncrystal contains. The zeroed local shows the intended call.
  • Suggested fix: alignCalorimeter(ptr, disk_align_params, crystal_align_params); — one line.

3. 🟠 [S1] CalAlignCrystal is not registered in DbTableFactory — the useDb:true path throws on first use.

  • Evidence: DbTableFactory.cc adds only CalAlignDisk; the unknown-name fallthrough is throw cet::exception("DBFILE_BAD_TABLE_NAME"). AlignedCalorimeterCache::initialize() creates DbHandle<CalAlignCrystal> whenever useDb is true.
  • Impact: the DB-backed mode is dead on arrival. Latent today (prolog default useDb:false), first-turn-on failure later.
  • Suggested fix: add the CalAlignCrystal case. Also worth stating in the PR body that cal.aligndisk/cal.aligncrystal need the DBA-side val.tables registration before useDb can ever be exercised.

4. 🟠 [S1] CMake plugin dependencies not updated to mirror the SConscript — CMake is the only link check that matters (--no-undefined).

  • Evidence: CaloCluster/src/SConscript gains mu2e_CaloConditions (mainlib+plugins) and mu2e_DbTables (plugins), but CaloCluster/CMakeLists.txt is untouched: the CaloClusterMaker plugin lists neither Offline::ProditionsService nor Offline::CaloConditions. The sibling precedent is explicit: StrawHitReco (the canonical ProditionsHandle consumer) links Offline::ProditionsService + its conditions library in its plugin block.
  • Impact: scons CI green proves nothing here; the CMake link of the module is at risk exactly per the repo's known scons↔CMake drift failure mode.
  • Suggested fix: add Offline::ProditionsService (and Offline::CaloConditions if the entity headers are reached) to the CaloClusterMaker plugin LIBRARIES, mirroring StrawHitReco.

5. 🟡 [S2] All three new headers have wrong include guards.

  • AlignedCalorimeterCache.hh: TrackerConditions_AlignedCalorimeterCache_hh (copy-paste from TrackerConditions).
  • AlignedCalorimeterMaker.hh: CalConditions_... (typo for CaloConditions).
  • AlignedCalConfig.hh: CaloConditions_... but the file lives in CaloConfig/.
  • Suggested fix: CaloConditions_AlignedCalorimeterCache_hh, CaloConditions_AlignedCalorimeterMaker_hh, CaloConfig_AlignedCalConfig_hh.

6. 🟡 [S2] readFile's EOF loop hangs on a malformed token.

  • Evidence: while (!ordFile.eof()) { ordFile >> ...; if (eof) break; ... } — a non-numeric token sets failbit, never eofbit; every subsequent >> is a no-op and the loop appends the stale values forever (unbounded memory, no diagnostic). Potential risk (needs a bad file), but alignment files are exactly the kind of hand-edited input that gets typos.
  • Suggested fix: while (ordFile >> index >> dx >> dy >> dz >> rx >> ry >> rz) { ... } and keep the count check after — fails loudly on any malformed line.

7. 🟡 [S2] The aligned/unaligned consumer split is undocumented.

  • Evidence: only CaloClusterMaker migrates to the aligned geometry. Everything downstream that interprets cluster positions — LineFinder's calo matching (diskToMu2e/mu2eToTracker), CalPatRec, TrackCaloMatching, the truth-match cog checks — still uses GeomHandle (unaligned).
  • Impact: zero today (disk_align.txt is identity), but the first non-zero DB commit makes cluster cog live in the aligned frame while consumers transform it with unaligned geometry. That rollout plan should be written down.
  • Suggested fix: a sentence in the PR body (or the maker header) naming which consumers migrate next and the constraint that sim/digitization must never see the aligned entity.

8. ⚪ [S3] Small items.

  • ProditionsService.cc now includes DAQConditions/inc/EventTimingCache.hh twice.
  • Commented-out filenameCrystal reads in both fromFcl/fromDb plus a config that has no filenameCrystal atom — either wire it or drop the comments (code-history comments).
  • ProditionsHandle<Calorimeter> constructed per produce() call; sibling modules hold it as a member.
  • Rotation convention undocumented: units of rx,ry,rz (radians?), composition order rotateX·rotateY·rotateZ, pivot = disk origin via setPose(origin+shift, rotation*rot). One comment in CalAlignParams.hh fixes it.
  • Title typo: "contition" → "condition".

🟢 Verified correct — no action

  • 🟢 The const_cast mutation cannot corrupt the GeomHandle original: DiskCalorimeter's copy ctor copies disks_ by value (std::vector<Disk>), G4Info_, and trackerCenter_ (the #1908 omission — fixed at main), then rebuildCrystalPtrs() repoints the crystal-pointer cache into the copy. The maker mutates only its private deep copy. This was the highest-risk item in the PR and it is clean.
  • 🟢 moveDisk/moveCrystal keep the object self-consistent: pose updated via setPose, every crystal's global position recomputed through the new pose, and all frame transforms (mu2eToDisk, diskToMu2e, FF variants) flow through the same pose. Neighbor caches are local-id-based post-#1908 and immune to pose moves.
  • 🟢 Proditions contract: cache registered under Calorimeter::cxname ("Calorimeter"), matching ProditionsHandle<Calorimeter>; DiskCalorimeter → Calorimeter entity resolution is fine; makeSet/makeIov/makeEntity follow the standard cache pattern with correct useDb guards.
  • 🟢 fcl contract: prolog alignedCalorimeter table ↔ AlignedCalConfig keys match; registered in both the Proditions prolog and the service config; disk_align.txt = 2 rows × 7 zeros = identity alignment for both disks.
  • 🟢 rowToCsv matches the TrkAlignElement sibling convention exactly (including the trailing comma — checked, it's the established pattern, not a defect).
  • 🟢 addRow enforces strict sequential indices — good defensive parsing.
  • 🟢 Link transitivity for the maker library: GeomHandle use in CaloConditions resolves via Offline::ProditionsService's PUBLIC link of Offline::GeometryService.

Validation check

  • Build/tests: 🟡 scons CI green at 2b0f3eda — but findings 1 and 4 live exclusively in the CMake build, which CI does not exercise. A local cmake configure (or spack dev-build) would catch both instantly.
  • Config contract: 🟢 pass.
  • Cross-repo: 🟢 none required in Production/trig-config while the entity has no non-identity data; DB-side val.tables registration needed before useDb (finding 3).

Residual risk

  • If merged as-is, the next spack build of Offline fails at CMake configure (finding 1) — the same downstream break as the crystalPos.txt incident.
  • No test exercises a non-zero alignment; a one-off job with a shifted disk demonstrating the cog moves accordingly would validate the sign/frame conventions end-to-end.

Author follow-ups

  1. Delete the two configure_file lines (finding 1).
  2. Pass the validated locals in fromDb (finding 2).
  3. Register CalAlignCrystal in the factory; note the val.tables prerequisite (finding 3).
  4. Mirror the SConscript deps into CaloCluster/CMakeLists.txt (finding 4).
  5. Fix the three include guards (finding 5).
  6. Harden readFile (finding 6) and document the rotation convention (finding 8).
  7. State the consumer-migration plan for the aligned entity (finding 7).

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