Add CaloEntrantTruthMaker: calo-entrant truth for calo MC hits - #1911
Add CaloEntrantTruthMaker: calo-entrant truth for calo MC hits#1911zwl0331 wants to merge 1 commit into
Conversation
For each CaloHitMC energy deposit, walk SimParticle::parent() and store the calo-entrant ancestor (highest ancestor that also deposited in the same disk) in a new transient CaloHitEntrantCollection, index-parallel to the input CaloHitMCCollection. Crystal/disk resolution prefers CaloHitMC::crystalID() when filled; files produced before that member existed (reads back -1) fall back to the CaloCluster<->CaloClusterMC pairing. Cardinality or null-Ptr violations of that pairing throw rather than degrade. Analysis choices (purity cut, ambiguity, cluster IDs) deliberately stay downstream; the product records ancestry facts only. Registered in both build systems (CMakeLists cet_build_plugin + SConscript; MF_MessageLogger added to the SCons plugin link list for the mf logging call). Validated byte-exact against the Python ancestry-walk reference on 200 MDC2025 events under envset p103: 6554/6554 contribution roots identical (fingerprint-matched across ntuple formats).
|
☀️ The build tests passed at 3c8f625.
N.B. These results were obtained from a build of this Pull Request at 3c8f625 after being merged into the base branch at f96d9fc. For more information, please check the job page here. |
|
1. [S2] The legacy fallback asserts a positional invariant The module's comment claims the cluster↔clusterMC hit lists are "positionally-matched … the invariant CaloClusterTruthMatch establishes." What that producer actually does (
The per-index pairing 2. [S2] The product has no dictionary — and the cited precedent (
3. [S2] The cluster collections are hard dependencies even when they are not needed.
4. [S3] Robustness / style
|
|
📝 The HEAD of |
This adds a producer that assigns each energy deposit in a CaloHitMC to its "calo-entrant" ancestor, i.e. the highest ancestor in the Geant4 parent chain that also deposited energy in the same disk. The point is to group secondary shower products (brem photons, conversion pairs, etc.) with the particle that started the shower, rather than treating every SimParticle as its own truth object. I need this for GNN clustering truth labels, but it is a generic truth definition, so it lives in CaloMC rather than in my analysis code.
Background: I originally tried to do this at the ntuple level by persisting the ancestor chains (EventNtuple#366). That was closed since truth matching like this belongs in an art module. This is that module. It walks SimParticle::parent() live, and only the resulting assignment is stored, no genealogy anywhere.
New files:
MCDataProducts/inc/CaloHitEntrant.hh: transient product (no dictionary, same pattern as CaloHitGraph). One entry per CaloHitMC, holding a vector ofPtr<SimParticle>entrants aligned withenergyDeposits(). The collection is index-parallel to the input CaloHitMCCollection.CaloMC/src/CaloEntrantTruthMaker_module.cc: the producer. Walks the parent chain for each (SimParticle, disk), stopping on a null parent (compression), and caches results per (simId, disk).Registered in both CMake and SConscript.
To get the disk of each hit the module uses CaloHitMC::crystalID() when it is filled. In older productions it is not (MDC2025 predates the member, and the CaloHit/CaloHitMC Assns does not survive compression), so there it falls back to the CaloCluster/CaloClusterMC index-parallel pairing; CaloHitMC entries not referenced by any cluster get null entrants in that mode. If collection sizes do not line up the module throws rather than truncating.
Validated on 200 MDC2025 events (run 001430): the assignment agrees with my existing Python implementation (which walks the ancestor chains persisted in files made with the old EventNtuple#366 patch) for all 6,554 contributions. Flattened through EventNtuple, the GNN truth labels built downstream come out byte-identical to my published pipeline (341/341 disk-graphs; a second file, 6,951 contributions, gives the same).
Two things I would like input on:
Ptr<CaloHitMC>per entry)? Right now consumers have to trust the configuration.Companion EventNtuple PR that flattens this into calohitsmc: Mu2e/EventNtuple#392