Add ALCARECO skims (KS, Lambda, D*, J/psi, Upsilon, Z) and persist resonance candidates#45
Open
davidwalter2 wants to merge 17 commits into
Open
Conversation
…sFromV0Selector Adds two ALCARECO streams for tracker alignment using KS->pi+pi- and Lambda0->p pi- decays, plus a new EDFilter (AlignmentTracksFromV0Selector) that extracts the unique daughter tracks from generalV0Candidates and stores them with their hits and clusters via the standard alignment helper::TrackCollectionStoreManager machinery. The selector follows the ObjectSelectorStream<> pattern of AlignmentTrackSelectorModule: a small selector struct with a select() method is wrapped via a typedef, inheriting all five produces<>() calls (TrackCollection + TrackExtras + TrackingRecHits + Strip/Pixel clusters) from helper::TrackSelectorBase and the cloneAndStore + put() flow from the StoreManagerTrait specialization. This avoids the combinatorial track-pair search done by AlignmentTwoBodyDecayTrackSelector when run on the full generalTracks collection, and ensures every V0Producer-accepted candidate's daughter tracks are preserved -- no raw vs. post-fit mass-window mismatch. Output cff also keeps generalTracks, dedxHarmonic2, dedxPixelHarmonic2 and dedxHitInfo so the dE/dx ValueMaps remain resolvable for V0 daughter tracks via candidate.daughter().get().track(). Event-level pre-filter is a CandViewCountFilter on generalV0Candidates (>=1 candidate); track-level cuts are inherited from V0Producer. No HLT trigger requirement so the streams are usable for any physics channel (W/Z+V0, Psi(2S)->J/psi KS via dimuon HLT, inclusive V0 production, ...). Co-Authored-By: Claude Opus 4.7 <[email protected]>
Replaces the previous AlignmentTracksFromV0Selector approach with a small EDProducer V0DaughterTrackProducer that extracts the unique daughter tracks from a private V0Candidates collection (ALCARECOTkAlV0Candidates, a clone of generalV0Candidates with a lower track-pT threshold). This keeps the standard reco V0 collection untouched. Adds a new EDProducer DeDxValueMapProjector that re-keys per-track dE/dx ValueMap<DeDxData> products from the generalTracks-keyed source onto the selected (cloned) ALCARECO track collection via TrackExtraRef.key(), emitting ValueMap<float> with just the dEdx scalar. Three projector instances per skim cover dedxHarmonic2 (strip), dedxPixelHarmonic2 (pixel) and a new joint strip+pixel Harmonic2-truncated estimator (alcaDedxJointEstimator, equivalent to dedxPixelAndStripHarmonic2T085 from RecoTracker/DeDx/python/dedxEstimators_cff.py). Output_cff for KS, Lambda and D* now keep the three projected dE/dx ValueMaps. The full generalTracks collection and original dE/dx maps are no longer needed in the ALCARECO output. Co-Authored-By: Claude Opus 4.7 <[email protected]>
Adds three plugins (Alignment/CommonAlignmentProducer/plugins/): - TwoBodyDecayCandidateProducer: builds a VertexCompositeCandidateCollection from opposite-sign track pairs in a configurable mass window, with optional muonSrc filter. Replaces the in-AlignmentTrackSelector pair finding for the dimuon ALCARECOs (J/psi, Upsilon, Z) so the candidate object can be persisted. Daughters use V0Producer's positive-charge-first convention. - AlignmentTrackSelectorWithIndexMapModule: drop-in replacement for AlignmentTrackSelectorModule that, alongside the standard cloned tracks + extras + hits + clusters, emits an edm::ValueMap<unsigned int> (instance label "originalIndex") whose value at each cloned track is its index in the source TrackCollection. The index is computed by pointer arithmetic on the selector chain's Track* output -- no kinematic fingerprinting. Required because helper::TrackCollectionStoreManager rewrites the cloned tracks' TrackExtraRefs to a fresh sequential key, destroying the link back to the source generalTracks. - VertexCompositeCandidateRemapper: rewrites each candidate's daughter TrackRefs to point at the AlignmentTrackSelector's cloned track output, using the originalIndex ValueMap chain (selH idx -> intermediateTracks idx -> intermediateTracks.extra().key() = generalTracks idx). Recurses into nested composites (e.g. for B -> J/psi K). Bug fix in DeDxValueMapProjector: previously used selectedTrack.extra().key() as the source-track index, which after StoreManager's clone is just the position in the new collection (0,1,2,...) -- so the persisted dE/dx values for V0 / D* daughters were actually values of unrelated generalTracks[j] entries. Switched to the same originalIndex chain. All five resonance ALCARECO streams (TkAlJpsiMuMu, TkAlUpsilonMuMu, TkAlZMuMu, TkAlKsToPiPi, TkAlLambdaToProtonPi) and the D* stream rewired to publish a *Resonances VertexCompositeCandidateCollection alongside the cloned-track output; the corresponding _Output_cff.py files keep the new products. Adds AlignmentTrackSelectorWithIndexMap_cfi. Adds recoskim_Run2016G_SingleMuon_AllResonances.py covering all streams in a single test job and removes the older partial test configs. Co-Authored-By: Claude Opus 4.7 <[email protected]>
ALCARECO PoolOutputModules had no splitLevel set, defaulting to 99 (fully split). Reading such files in CMSSW >= 15_0 hits ROOT cms-sw#19773 (I/O rule not applied for split branches): the SiStripCluster v11->v14 schema rule does not fire and clusters come back empty, breaking the CVH refit. Add a dataTier-based customise (setAlcaRecoSplitLevel) that sets splitLevel=1 on every ALCARECO output module, keeping collection items streamed together so the rule fires. ~1-2% size impact; mirrors MiniAOD's slimmedMuonTrackExtras SiStripCluster (split level 1). Wired into the cmsDriver --customise list so it survives regeneration. Co-Authored-By: Claude Opus 4.7 <[email protected]>
…lor eta cut, fix psi(2S) channel to prompt pi pi
…ertex-info passthrough - JpsiXCandidateProducer (vcc mode): veto X candidates that reuse one of the J/psi muon tracks, mirroring the jpsiDaughterKeys veto in track mode; prevents duplicate-track mother candidates (and double-fed tracks in the preset-C multi-track fit). - signedPdgId helper in JpsiXCandidateProducer + TwoBodyDecayCandidateProducer: leptons keep pdgId sign opposite to charge (mu- = +13), hadrons follow the track charge (K+ = +321); previously a K+ track was tagged -321. Sign now derived from the actual track charge, so same-sign pairs are self-consistent too. - VertexCompositeCandidateRemapper: carry vertex covariance and fit chi2/ndof into the remapped candidates instead of dropping them. - TwoBodyDecayCandidateProducer: guard KalmanVertexFitter::vertex() against VertexException (treat as dropped pair, don't kill the job). - AlignmentThreeBodyDecayTrackSelector: end-of-job summary via MessageLogger instead of std::cout. - ALCARECOTkAlJpsiX_cff: correct stale comments still classifying psi(2S) as a V0-mode channel (it uses the prompt dipion producer). Co-Authored-By: Claude Fable 5 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds ALCARECO skims for the muon-momentum-scale calibration covering V0
(KS, Lambda), three-body (D*), dimuon (J/psi, Upsilon, Z) and J/psi+X
(B-meson / quarkonium) channels, and persists a
reco::VertexCompositeCandidateCollectionper stream so downstreamconsumers can iterate the candidates and follow daughter
TrackRefs intothe cloned ALCAReco track collection without going back to
generalTracks:TkAlKsToPiPi— V0 (KS → π⁺π⁻)TkAlLambdaToProtonPi— V0 (Λ → pπ⁻)TkAlDstToD0Pi— D*⁺ → D⁰(K⁻π⁺) πs⁺ (three-track topology with a soft-pion tag)TkAlJpsiMuMu,TkAlUpsilonMuMu,TkAlZMuMu— dimuon resonances (V0-pattern: candidate is built upstream byTwoBodyDecayCandidateProducer)TkAlJpsiX— 8 channels: B⁺ → J/ψK⁺, B⁰ → J/ψK*⁰, B⁰ → J/ψKs, Bs → J/ψφ, Λb → J/ψΛ, ψ(2S) → J/ψπ⁺π⁻, Bc⁺ → J/ψπ⁺, plus a J/ψ-only channel on a loose muon selectionEach skim stores the daughter tracks (cloned, with hits + clusters) and
publishes
*Resonancescandidate collections with daughterTrackRefsinto the cloned tracks. Selection cuts (mass window, charge, V0 Lxy /
cosθXY) are applied at the candidate-builder level.
What's in this PR
16 commits on top of
6e29f933a55, in three blocks:Block 1 — V0 / D* / dimuon skims + resonance persistence (commits 1–6)
0960cf87c4f— Infrastructure forTkAlDstToD0Pi(Elisabetta Manca): three-body decay selector module + ALCARECO cff + validation analyzer37b68d22f1f— Removes the validation analyzer (kept the selector)3149b4a77a1— Removes HLT preselection so the ALCARECO is usable across triggers1d2bf1a7599— AddsTkAlKsToPiPi+TkAlLambdaToProtonPiV0 skims viaAlignmentTracksFromV0Selectorc932a392d9d— ReplacesAlignmentTracksFromV0SelectorwithV0DaughterTrackProducer(extracts daughter tracks from a privateALCARECOTkAlV0Candidatescollection — a clone ofgeneralV0Candidateswith a lower track-pT cut, leaving the standard reco V0 collection untouched). Adds optional per-track dE/dx ValueMap projection (strip / pixel / joint Harmonic-2) for downstream particle-ID.df64a66c5fb— Persists the resonance-candidate collection for every stream and adds dimuon streams (J/psi, Upsilon, Z) on the V0 pattern.Block 2 — output format (commit 7)
b8ebaa3d9f2— Writes ALCARECO PoolOutputModules at ROOT split level 1 (alcarecoSplitLevel.pycustomise) so 10_6-produced files stay readable in CMSSW ≥ 15_0 (works around ROOT Replace boost with standard library equivalents cms-sw/cmssw#19773: v11→v14SiStripClusterschema-evolution read rule not firing on fully-split branches).Block 3 — TkAlJpsiX stream (commits 8–16, Pietro Lugato)
4d65009c736— registersTkAlJpsiXin central AlCa (autoAlca.py: Charmonium, MuOniaParked;AlCaRecoStreams_cff.py,AlCaRecoOutput_cff.py)86af90df597— helix propagation of daughter tracks to a candidate-level common point + moreTwoBodyDecayCandidateProduceroptions5952d2d08bb— BuildFile dependencies for the J/psi+X producers (KinematicFit, TransientTrack, …)e20a850141f—CompositeDaughterTrackProducer: merged, deduplicated leaf-track collection across all channels04efb4538e5—JpsiXCandidateProducercovering all 7 J/psi+X decay channels (track mode for B⁺/Bc, VCC mode for nested resonances)c560219c6bf— TkAlJpsiX output module keep/drop list026705dd9ec— cff wiring of the 7 channels, V0 clone with reduced pT floor, per-channel remappers420fe8859d8— persists muon info (ALCARECOTkAlJpsiXLooseMuons+AlignmentTrackToMuonAssociatortrack→muon association), adds the J/ψ-only channel on a loose muon ID, fixes the bachelor-eta cut, and rewires ψ(2S) to prompt π⁺π⁻ (was incorrectly sourced from the displaced V0 Ks output)e77e7e0a5a6— requires high-purity tracks (D*) and per-daughter pT thresholdsCommit 6 details
TwoBodyDecayCandidateProducer: builds aVertexCompositeCandidateCollectionfrom opposite-sign track pairs in a configurable mass window, with optional muon-ID prefilter viamuonSrc. Replaces the in-AlignmentTrackSelectorpair finding for the dimuon streams; daughters use V0Producer's positive-charge-first convention.AlignmentTrackSelectorWithIndexMapModule: drop-in replacement forAlignmentTrackSelectorModulethat, alongside the standard clonedTrack+TrackExtra+RecHit+Clusteroutputs, emits anedm::ValueMap<unsigned int>(instance labeloriginalIndex) of source-collection indices computed by pointer arithmetic on the selector chain'sTrack*output. No kinematic fingerprinting. Required becausehelper::TrackCollectionStoreManager::processTrackrewrites the cloned tracks'TrackExtraRefs to a fresh sequential key, destroying the link togeneralTracks.VertexCompositeCandidateRemapper: rewrites each candidate's daughterTrackRefs to point at the cloned ALCAReco track collection via theoriginalIndexValueMap chain (selH idx → intermediateTracks idx →intermediateTracks.extra().key()= generalTracks idx). Recurses into nested composites (e.g. for B → J/psi K).DeDxValueMapProjector: previously usedselectedTrack.extra().key()as the source-track index, but afterTrackCollectionStoreManager's clone-and-store that key is just the position in the new collection (0,1,2,…). The persisted dE/dx values for V0 / D* daughters were therefore values of unrelatedgeneralTracks[j]entries. Switched to the sameoriginalIndexchain.*ResonancesVertexCompositeCandidateCollectionalongside the cloned-track output; the corresponding_Output_cff.pyfiles keep the new products.recoskim_Run2016G_SingleMuon_AllResonances.pycovering all streams in a single test job; removes the older partial test configs (Dst,KsLambda,KsLambdaDst).TkAlJpsiX details (block 3)
Five-stage single-sequence architecture (
ALCARECOTkAlJpsiX_cff.py):DCS filter + muon selectors → shared candidate construction (J/ψ, V0s, K*⁰, φ, π⁺π⁻) → 8 per-channel
JpsiXCandidateProducer/TwoBodyDecayCandidateProducerinstances → merged deduplicated leaf-track collection (CompositeDaughterTrackProducer) →AlignmentTrackSelectorWithIndexMapcloning + 3 dE/dx projectors → 8 per-channelVertexCompositeCandidateRemappers. The persisted output is a single deduplicated cloned-track collection + 8 remapped candidate collections + persisted loose muons + a track→muonedm::Association.JpsiXCandidateProducer: two modes —track(bachelor fromgeneralTracks; B⁺, Bc) andvcc(secondVertexCompositeCandidate; B⁰, Bs, Λb, ψ(2S)). Dimuon (and X-pair) 4-momenta are helix-propagated to their pair PCA before the mass calculation (removes an O(1–3 MeV) ctau-correlated bias at displaced vertices). Optional J/ψ mass constraint and B-levelKinematicConstrainedVertexFitterfit with vertex-prob / pointing-angle / Lxy-significance cuts.TKALJPSIX_SELECTION_PRESETenv var at python-load time; default B.ALCARECOTkAlV0Candidatesclone loosens vertex-quality and IP-significance cuts (vtxChi2Cut6.63→15,vtxDecaySigXYCut15→10,cosThetaXYCut0.998→0.995,tkIPSigXYCut2→1) on top of the pT floor 0.35→0.1 GeV, for the alignment use case only.New plugins
Alignment/CommonAlignmentProducer/plugins/V0DaughterTrackProducer.cc— KS / Λ daughter extractionAlignment/CommonAlignmentProducer/src/AlignmentThreeBodyDecayTrackSelector.cc— D* daughter selection (used by the existingAlignmentTrackSelectorModule)Alignment/CommonAlignmentProducer/plugins/DeDxValueMapProjector.cc— per-track dE/dx ValueMap projector (ref-based viaoriginalIndex)Alignment/CommonAlignmentProducer/plugins/TwoBodyDecayCandidateProducer.cc— two-track candidate builder (dimuon, K*⁰, φ, π⁺π⁻; asymmetric mass hypotheses, optional Kalman vertex fit, track-track DOCA cut)Alignment/CommonAlignmentProducer/plugins/AlignmentTrackSelectorWithIndexMapModule.cc— selector + originalIndex ValueMapAlignment/CommonAlignmentProducer/plugins/VertexCompositeCandidateRemapper.cc— candidate daughter-ref remapperAlignment/CommonAlignmentProducer/plugins/JpsiXCandidateProducer.cc— J/ψ+X mother-candidate builder (7 channels)Alignment/CommonAlignmentProducer/plugins/CompositeDaughterTrackProducer.cc— merged deduplicated leaf-track extraction from nested candidatesAlignment/CommonAlignmentProducer/plugins/AlignmentTrackToMuonAssociator.cc— cloned-track →reco::MuonassociationNew cff/cfi
ALCARECOTkAlV0Candidates_cff.py(private V0Producer clone, shared by V0 skims and TkAlJpsiX)ALCARECOTkAl{KsToPiPi,LambdaToProtonPi,DstToD0Pi,JpsiMuMu,UpsilonMuMu,ZMuMu,JpsiX}_cff.py+ each_Output_cff.pyalcaDedxJointEstimator_cfi.pyAlignmentTrackSelectorWithIndexMap_cfi.pyalcarecoSplitLevel.py(split-level-1 customise function)TkAlLooseIdMuonSelectoradded toTkAlMuonSelectors_cfi.pyPlus updates to
BuildFile.xml,AlCaRecoOutput_cff.py,AlCaRecoStreams_cff.py,AlignmentTrackSelector_cfi.py(newThreeBodyDecaySelectorPSet), andautoAlca.py.Test plan
scram b -j16inCMSSW_10_6_17_patch1edmDumpEventContentshows the new*_*Resonances_*_*candidate branchesTrackRefs resolve into the cloned ALCAReco track collection (100% id-match on the first candidate of every event across all streams)originalIndex-chain bug fix)scram b -j8) clean after merging the TkAlJpsiX commits (block 3)Review fixes applied (commit
444b20f2062)JpsiXCandidateProducervcc mode: added the missing overlap veto between the J/ψ muon tracks and the X-candidate daughter tracks (track mode already had one viajpsiDaughterKeys). Previously a K*⁰/φ/π⁺π⁻ candidate reusing a J/ψ muon produced a duplicate-track mother candidate — the DOCA cut passed trivially (DOCA = 0) and, under preset C, the multi-track Kalman fit received the same track twice.pdgIdsigns: hadrons now carry the sign of the track charge (K⁺ =+321; previously tagged-321by the lepton convention); leptons unchanged (μ⁻ =+13). Sign is derived from the actual track charge, so same-sign pairs are self-consistent.VertexCompositeCandidateRemapper: remapped candidates now carry the source candidate's vertex covariance and fit χ²/ndof (previously dropped).TwoBodyDecayCandidateProducer:KalmanVertexFitter::vertex()exception-guarded (aVertexExceptiondrops the pair instead of killing the job); dormant sinceapplyVertexFit=Falseeverywhere, but safe if enabled.AlignmentThreeBodyDecayTrackSelector: end-of-job summary via MessageLogger instead ofstd::cout.ALCARECOTkAlJpsiX_cff.py.Open items from review
TKALJPSIX_SELECTION_PRESETenv-var switch is convenient for private production but makes the cff non-reproducible from the config file alone; central AlCa integration would need it replaced by a cms.Parameter / customise function.ALCARECOTkAlJpsiXGoodMuons,filter=True), so events whose muons are all loose-only are not captured.🤖 Generated with Claude Code