Skip to content

Commit 9bd67e9

Browse files
Cosmics: collect the raw clusters of matched cosmics and tag them with TOF (--enable-cluster-output)
The async reconstruction stores neither TPC tracks nor TPC clusters, so the leg references of TrackCosmics cannot be resolved offline. New device cosmics-cluster-collector (+ cosmics-full-writer -> o2_cosmics_full.root, tree cosmicsFull, one entry per TF): - per cosmic (o2::dataformats::CosmicTrack, DataFormatsGlobalTracking): the TrackCosmics, the TPC tracks of both legs, the raw ClusterNative + sector/row of each leg's attached clusters and of all clusters in a road around the leg (flags: attached / road / used by any TPC track / found with the absolute time on the other TPC side), the ITS compact clusters (chip, anchor pixel, pattern ID, ROF BC; pattern bytes for patterns not in the dictionary), TOF clusters (raw time, ToT, channel), TRD tracklet words (+ trigger BC), MC label; per TF: TFIDInfo and vDrift / t0 of the TPC transformation. Only raw detector data are stored: TPC transformation, TOF calibration, ITS dictionary and geometry are applied offline. - TPC road: each leg's helix through all pad rows of its side, in the frame of its own time0, at the real x of the row, points beyond the leg's closest approach skipped; predicted real (y, z) mapped to nominal coordinates with the inverse correction; clusters within --corridor-width (1 cm) taken. The other TPC side is searched when the time of the cosmic is known (CE-crossing leg, z-continuity time with error < --max-abs-time-err 0.5 mus, or a TOF time). - TOF tag: all TOF clusters within the cosmic's time window and the road (--tof-road-width 5 cm) are candidates per leg; the top/bottom pair whose time difference matches the muon's flight along the helix (|t_top - t_bottom + L/c| < --tof-flight-tolerance 2 ns, z of one-side legs shifted to the pair's mean time) gets HitTOFFlight and the cosmic its TOF time (CosmicTrack::timeTOFMUS); without such a pair the closest hit per leg is kept. The same search in the impossible order (bottom hit first) only finds accidental pairs: its best score is stored next to the flagged pair's (scoreTOFPair / scoreTOFReversed) as QA of the flag's background. - The TOF time (--tof-time-error 0.1 mus) then fixes the other-side TPC corridor, the TRD road (trigger and z, --trd-road-width) and the ITS road (readout frame and z, --its-road-width); without it the TPC time is used. - Duplicates: per TF the cosmics are ranked (TOF time first, then more attached TPC clusters); one sharing >= 30 % of the smaller one's TPC clusters with a better one gets duplicateOf = that one's entry (a leg split into two TPC tracks). Nothing is removed. - Polish: cosmics with a TOF time are refitted at it (TPC-only legs: bottom leg inward to the closest approach to the beam line, top leg inward to the same point, halves combined; muon mass and energy loss along the flight as in the matcher), CosmicTrack::polished with chi2MatchPolished (< 0: not polished). The matcher's time is the bracket-overlap centre for one-side legs on the same side (tens of mus off), which puts the inner material at the wrong z. Check: polished at the matcher's time instead, the cosmic MC reproduces the matcher (chi2Match median 79.1 vs 79.2, q/pt within 7e-4). - Legs nearly parallel to the pad rows (closest approach to the beam line inside the TPC or at its inner edge): the row-by-row road cannot reach the rows, there the helix is followed in steps of path length and the rows within the road width are searched. - A TOF time can be negative (cosmic just before the TF start): the flag is CosmicTrack::hasTOFTime() (scoreTOFPair >= 0). - At most --max-cosmics-per-tf (100) cosmics per TF are written (protection against fake-dominated settings). - --debug-tree: cosmics_collector_debug.root, tree "cosmics" with one entry per cosmic (matching and timing quantities, vectors of the transformed TPC clusters, road points, ITS / TOF / TRD hits). Off by default. Validation: the road re-finds 99.8 % of the legs' own clusters in the cosmics run 562658 and 97 % in PbPb 2025 with the v10n correction map. PbPb 2025 LHC25an 567939 (600 TFs, preset physics-v1): 30 of 224 cosmics TOF-tagged (10 with legs on opposite TPC sides, 20 on one side), 0 pairs in the impossible order (flag purity >= 90 % at 95 % CL), flight-time residual centred at 0 within 0.2 ns; 10 duplicates. 568041 reconstructed from CTF (10546 TFs): 3203 cosmics, 435 TOF-tagged non-duplicates, 90 duplicates. CPU: matcher + collector ~0.6 s per PbPb TF; output ~1.5 kB per TF. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 7479fef commit 9bd67e9

9 files changed

Lines changed: 1856 additions & 1 deletion

File tree

‎DataFormats/Detectors/GlobalTracking/CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,4 +45,5 @@ o2_target_root_dictionary(
4545
DataFormatsGlobalTracking
4646
HEADERS include/DataFormatsGlobalTracking/FilteredRecoTF.h
4747
include/DataFormatsGlobalTracking/TrackTuneParams.h
48+
include/DataFormatsGlobalTracking/CosmicTrack.h
4849
)
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file CosmicTrack.h
13+
/// \brief Matched cosmic track with the raw clusters of its legs and of the road around them, for offline refits
14+
15+
#ifndef ALICEO2_COSMIC_TRACK_H
16+
#define ALICEO2_COSMIC_TRACK_H
17+
18+
#include <vector>
19+
#include <cstdint>
20+
#include <Rtypes.h>
21+
#include "ReconstructionDataFormats/TrackCosmics.h"
22+
#include "DataFormatsTPC/TrackTPC.h"
23+
#include "DataFormatsTPC/ClusterNative.h"
24+
#include "SimulationDataFormat/MCCompLabel.h"
25+
26+
namespace o2::dataformats
27+
{
28+
29+
/// raw TPC cluster with its address; transformed coordinates are not stored (re-transform offline with the calibration of the TF)
30+
struct CosmicTPCCluster {
31+
enum Flags : uint8_t {
32+
Attached = 0x1, ///< attached to the TPC track of this leg
33+
Corridor = 0x2, ///< found in the road around the leg
34+
Used = 0x4, ///< attached to some TPC track (for corridor clusters: another track, e.g. a split piece of the leg)
35+
AbsTime = 0x8 ///< found on the other TPC side with the absolute time of the cosmic instead of the time0 of the leg: CosmicTrack::timeTOFMUS
36+
///< if >= 0, else the time of CosmicTrack::cosmic
37+
};
38+
o2::tpc::ClusterNative cl{}; ///< raw cluster: time, pad, widths, charges, flags
39+
uint8_t sector = 0;
40+
uint8_t row = 0;
41+
uint8_t flags = 0;
42+
bool isAttached() const { return flags & Attached; }
43+
bool isCorridor() const { return flags & Corridor; }
44+
bool isUsed() const { return flags & Used; }
45+
bool isAbsTime() const { return flags & AbsTime; }
46+
ClassDefNV(CosmicTPCCluster, 1);
47+
};
48+
49+
/// origin of the ITS / TOF / TRD hits of a cosmic
50+
enum CosmicHitFlags : uint8_t {
51+
HitMatched = 0x1, ///< part of the leg's matched global track
52+
HitRoad = 0x2, ///< found by the road search around the cosmic
53+
HitTOFFlight = 0x4 ///< TOF road hit of the top/bottom pair whose time difference matches the muon's flight (fixes the cosmic's time)
54+
};
55+
56+
/// ITS cluster of a leg: the raw compact cluster (chip, anchor pixel, pattern ID) and its ROF; no coordinates (the dictionary and the
57+
/// geometry are applied offline)
58+
struct CosmicITSCluster {
59+
uint16_t chipID = 0;
60+
uint16_t row = 0;
61+
uint16_t col = 0;
62+
uint16_t pattID = 0;
63+
int32_t pattEntry = -1; ///< start of the pattern bytes in CosmicTrack::itsPatterns (pattern not in the dictionary or group pattern), -1: none
64+
int32_t rofBC = 0; ///< start of the cluster's ROF in BCs since the start of the TF
65+
uint8_t leg = 0; ///< 0 bottom, 1 top
66+
uint8_t flags = 0; ///< CosmicHitFlags
67+
ClassDefNV(CosmicITSCluster, 1);
68+
};
69+
70+
/// TOF cluster of a leg: matched to its track or found on the road
71+
struct CosmicTOFCluster {
72+
double timeRaw = 0.; ///< raw TOF time [ps] (the calibration is applied offline)
73+
float tot = 0.f; ///< time over threshold
74+
int32_t channel = -1;
75+
uint8_t leg = 0;
76+
uint8_t flags = 0; ///< CosmicHitFlags
77+
ClassDefNV(CosmicTOFCluster, 1);
78+
};
79+
80+
/// TRD tracklet of a leg: attached to its track or found on the road
81+
struct CosmicTRDTracklet {
82+
uint64_t word = 0; ///< raw Tracklet64 word
83+
int32_t trigBC = 0; ///< BC of its trigger since the start of the TF
84+
uint8_t layer = 0;
85+
uint8_t leg = 0;
86+
uint8_t flags = 0; ///< CosmicHitFlags
87+
ClassDefNV(CosmicTRDTracklet, 1);
88+
};
89+
90+
/// matched cosmic with everything needed for an offline refit
91+
struct CosmicTrack {
92+
o2::dataformats::TrackCosmics cosmic{}; ///< matcher output (time in mus; the leg references are only valid within the TF)
93+
o2::tpc::TrackTPC tpcBottom{}; ///< TPC part of the bottom leg (default if none); z refers to its time0; its cluster
94+
///< references are only valid within the TF: the clusters are in clTPCBottom
95+
o2::tpc::TrackTPC tpcTop{}; ///< TPC part of the top leg
96+
std::vector<CosmicTPCCluster> clTPCBottom; ///< attached + corridor TPC clusters of the bottom leg
97+
std::vector<CosmicTPCCluster> clTPCTop; ///< same for the top leg
98+
std::vector<CosmicITSCluster> clITS; ///< ITS clusters of the legs' matched tracks and on the road
99+
std::vector<uint8_t> itsPatterns; ///< pattern bytes (row span, column span, bitmap) of the ITS clusters that need them
100+
std::vector<CosmicTOFCluster> clTOF; ///< TOF clusters of the legs' matched tracks and on the road
101+
std::vector<CosmicTRDTracklet> trdTracklets; ///< TRD tracklets of the legs' matched tracks and on the road
102+
float timeTOFMUS = -1.f; ///< time of the cosmic [mus since the TF start, negative before it] from its HitTOFFlight pair (valid if hasTOFTime())
103+
float scoreTOFPair = -1.f; ///< score of the HitTOFFlight pair: road and flight-time residuals squared in units of the cuts (< 0: none)
104+
float scoreTOFReversed = -1.f; ///< same for the best pair in the impossible order (bottom hit first) = an accidental coincidence:
105+
///< QA of the flag's background; comparable to scoreTOFPair = ambiguous TOF time (< 0: none)
106+
int duplicateOf = -1; ///< entry (in the TF) of the cosmic this one duplicates: the same muon matched twice (e.g. a leg split
107+
///< into two TPC tracks): >= 30 % of the smaller one's TPC clusters shared with a better one (TOF time,
108+
///< more attached clusters) (-1: none)
109+
o2::track::TrackParCov polished{}; ///< refit at the TOF time (TPC-only legs, muon mass, energy loss along the flight), at the closest
110+
///< approach to the beam line; valid if chi2MatchPolished >= 0
111+
float chi2MatchPolished = -1.f; ///< chi2 of the polished bottom and top halves at the closest approach (< 0: not polished)
112+
o2::MCCompLabel label{}; ///< MC label of the cosmic (MC only)
113+
114+
bool hasTOFTime() const { return scoreTOFPair >= 0.f; } ///< a HitTOFFlight pair gave the cosmic its time timeTOFMUS
115+
ClassDefNV(CosmicTrack, 1);
116+
};
117+
118+
/// per-TF quantities of the TPC transformation used in the reconstruction
119+
struct CosmicsTFInfo {
120+
float vDrift = 0.f; ///< drift velocity of the transformation [cm/time bin]
121+
float t0 = 0.f; ///< time offset of the transformation [time bins]
122+
ClassDefNV(CosmicsTFInfo, 1);
123+
};
124+
125+
} // namespace o2::dataformats
126+
127+
#endif

‎DataFormats/Detectors/GlobalTracking/src/DataFormatsGlobalTrackingLinkDef.h‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,16 @@
2222
#pragma link C++ class o2::globaltracking::TrackTuneParams + ;
2323
#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::globaltracking::TrackTuneParams> + ;
2424

25+
#pragma link C++ class o2::dataformats::CosmicTPCCluster + ;
26+
#pragma link C++ class std::vector < o2::dataformats::CosmicTPCCluster> + ;
27+
#pragma link C++ class o2::dataformats::CosmicITSCluster + ;
28+
#pragma link C++ class std::vector < o2::dataformats::CosmicITSCluster> + ;
29+
#pragma link C++ class o2::dataformats::CosmicTOFCluster + ;
30+
#pragma link C++ class std::vector < o2::dataformats::CosmicTOFCluster> + ;
31+
#pragma link C++ class o2::dataformats::CosmicTRDTracklet + ;
32+
#pragma link C++ class std::vector < o2::dataformats::CosmicTRDTracklet> + ;
33+
#pragma link C++ class o2::dataformats::CosmicTrack + ;
34+
#pragma link C++ class std::vector < o2::dataformats::CosmicTrack> + ;
35+
#pragma link C++ class o2::dataformats::CosmicsTFInfo + ;
36+
2537
#endif

‎Detectors/GlobalTrackingWorkflow/CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ o2_add_library(GlobalTrackingWorkflow
2626
src/StrangenessTrackingWriterSpec.cxx
2727
src/CosmicsMatchingSpec.cxx
2828
src/TrackCosmicsWriterSpec.cxx
29+
src/CosmicsClusterCollectorSpec.cxx
2930
src/TOFMatcherSpec.cxx
3031
src/TOFMatchChecker.cxx
3132
src/HMPMatcherSpec.cxx
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// @file CosmicsClusterCollectorSpec.h
13+
/// @brief Collects the raw clusters of matched cosmics (attached + road around the legs) for offline refits
14+
15+
#ifndef O2_COSMICS_CLUSTER_COLLECTOR_SPEC_H
16+
#define O2_COSMICS_CLUSTER_COLLECTOR_SPEC_H
17+
18+
#include "Framework/DataProcessorSpec.h"
19+
#include "ReconstructionDataFormats/GlobalTrackID.h"
20+
#include "DetectorsCommonDataFormats/DetID.h"
21+
22+
namespace o2::globaltracking
23+
{
24+
25+
/// create a processor spec collecting the clusters of the cosmics found by the cosmics-matcher
26+
/// roadDets: detectors (ITS, TOF, TRD) whose hits along the cosmic are collected besides the TPC road
27+
framework::DataProcessorSpec getCosmicsClusterCollectorSpec(o2::dataformats::GlobalTrackID::mask_t src, bool useMC, bool itsStag, o2::detectors::DetID::mask_t roadDets);
28+
29+
} // namespace o2::globaltracking
30+
31+
#endif

‎Detectors/GlobalTrackingWorkflow/include/GlobalTrackingWorkflow/TrackCosmicsWriterSpec.h‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ namespace globaltracking
2727
/// write cosmics tracks to a root file
2828
framework::DataProcessorSpec getTrackCosmicsWriterSpec(bool useMC);
2929

30+
/// write cosmics with their raw clusters (cosmics-cluster-collector output) to a root file
31+
framework::DataProcessorSpec getCosmicsFullWriterSpec();
32+
3033
} // namespace globaltracking
3134
} // namespace o2
3235

0 commit comments

Comments
 (0)