Skip to content

Commit d24f2c1

Browse files
MatchCosmics: cosmics in collision data + raw-cluster writer with TOF (#15915)
* MatchCosmics: include the last compatible vertex in the DCA veto vtIDMax is the id of the last compatible vertex (inclusive), but the veto loop stopped before it: a seed associated to a single vertex (vtIDMin == vtIDMax) was never checked, so with --use-pv-info the DCA cut never removed collision tracks associated to one vertex. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * MatchCosmics: selection of cosmics in collision data, named presets In collision data nearly all seeds are collision tracks and TPC-only legs had their z ignored, so any two tracks back-to-back in the transverse plane were paired (PbPb: minutes per TF, tens of thousands of fake pairs). New settings, all off by default and switched on together by the preset physics-v1 (o2-cosmics-match-workflow --cosmics-preset physics-v1; --configKeyValues can still override single keys, unknown names are fatal): - Seed cuts: minSeedNClTPC, minSeedDCAxy and minSeedDCAxyNSigma reject short TPC fragments and seeds passing the beam line (cosmics through the beam line are indistinguishable from collision tracks anyway). - z test of TPC-only legs (constrainTPCOnlyZ): a one-side TPC-only track has z relative to its time0, z(t) = z + side*vD*(t-time0); a CE-crossing or non-TPC-only track has an absolute z. The legs are compared at a common time (same side, or one leg with known time); for legs on opposite sides z continuity fixes the common time, which must lie in both time brackets. That time, with its error sigma_z / (2 vD) (~0.3 mus), is used for the refit and as the time of the cosmic (before: the centre of the bracket overlap, tens of mus, which put the legs at the wrong z: cosmics run 562658 A x C chi2Match median 3.5e4 -> 43). For all other pairs the time error of the cosmic stays the half-width of the bracket overlap. - Same-half veto (vetoSameHalf): pairs whose two legs lie on the same side of the closest approach in the transverse plane (two pieces of one leg) are rejected; skipped when a leg's reference point is within 20 cm of the closest approach. - maxChi2Match: cut on the chi2 of the refitted top/bottom legs. - minPtOppositeSides: for TPC-only legs on opposite sides z continuity defines the time, so z does not reject random pairs (94 % of the PbPb candidates). Both legs (in checkPair, before the winner selection) and the refitted cosmic need pT above it (scaled with the field). Unconditionally, the seeds and the refit use the muon mass (and charge 1) for the material corrections instead of the TPC track's PID from dE/dx (a leg tagged as kaon or proton got that mass): cosmic MC 6987 -> 7003 correct pairs (0 wrong), cosmics run 562658 357 -> 358; the refitted q/pt changes by +-0.4 % (MC) and +-1 % (562658) (q16-q84, pT < 20 GeV). physics-v1: pT > 1 GeV, |DCA_xy| > 3 cm and > 10 sigma, >= 30 TPC clusters; systematic errors for the leg comparison y 0.5 cm, snp 0.02, q/pt 0.05 (true pairs had pulls 2-4x too wide) with crude chi2 < 50; open per-parameter windows except tgl (3 sigma); chi2Match < 1000; z test and same-half veto on; minPtOppositeSides 2 GeV. Validation, TPC-only legs: cosmic MC with PbPb-like distortions 7003 of 8638 cosmics correct (81.1 %, 0 wrong pairs); cosmics run 562658 358 cosmics; PbPb 2025 LHC25an 567939 (19 kHz) 0.37 cosmics per TF (3.90 without the pT cut), 568041 reconstructed from CTF 0.30 per TF (3203 in 10546 TFs; the PbPb numbers before the muon mass, which leaves 4 PbPb TFs unchanged). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * MatchCosmics: energy-loss sign along the muon's flight; optional energy-loss sign in the TPC refit The propagator applies the energy-loss correction along the direction of the track parameters (loss forward, gain backward), and refitWinners fits a cosmic from the bottom leg to the top one: after the inward refit of the bottom leg its parameters are inverted and carried up through the top leg, i.e. they describe a particle moving upward. A cosmic muon flies downward, from the top leg to the bottom leg, so only the inward refit of the bottom leg (backward along its parameters = backward along the flight) had the physical sign; the propagation of the inverted bottom leg to the top leg, the outward refit of the top leg, the inward refit of the top leg, its propagation to the bottom parameter and the propagation of the top seeds to the DCA had the opposite one. The sign is now imposed along the flight in all of them, with the propagator's signCorr argument. GPUO2InterfaceRefit / GPUTrackingRefit::RefitTrackAsTrackParCov (TrackParCov + cluster references) get the analogous optional last argument eLossSign, passed to their propagations (0 = along the parameters as before, +1 gain, -1 loss; flipped on the optional way to the reference X when that runs against the refit direction); the default keeps the behaviour for all other users. MC truth (cosmic MC, 1073 muons crossing the inner region; true parameters at the bottom TPC inner radius propagated back through the closest approach to the top one, compared to the true momentum there, q16 / q50 / q84 in MeV): true loss between the two 14.5 / 16.1 / 19.9 MeV (median for |z| at the closest approach 0-25 / 25-50 / 50-75 cm); predicted - true with the sign of the upward fit -14.5 / -15.2 / -18.6 MeV (as without material: the gain inward and the loss outward cancel), with the sign along the flight +1.2 / +2.1 / +1.0 MeV (spread q16-q84 about -2 ... +9 MeV). The matched cosmics hardly change because the two halves' errors cancel in their average: cosmic MC 7003 -> 7006 correct pairs (0 wrong), chi2Match median unchanged; cosmics run 562658 358 cosmics before and after; refitted q/pt within +-0.05 %. The halves themselves (e.g. the momentum at the TPC entrance) change by the full loss. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * 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> * MatchCosmics: compare same-side TPC-only legs refitted at a common time A TPC-only track has no time measurement: its time0 is the tracker's guess (GPUTPCGMTrackParam::ShiftZ: z = 0 at the beam line if the helix can come from it, otherwise the latest cluster at z = 0.521 * x, then clamped to the drift volume). For a cosmic, which does not come from the beam line, the two legs get independent guesses, typically tens of mus apart, so their clusters were distortion-corrected at different z and the legs disagree (y, snp, q/pt) although they are one track. For legs on opposite sides the time comes from z continuity, but legs on the same side were compared as tracked. New MatchCosmicsParams refitSameSideAtCommonTime (default false, not in the preset physics-v1, see below): after the cheap cuts (tgl, q/pt, same half), same-side TPC-only legs are refitted at the centre of their brackets' overlap (the time the refit of the winners uses) and compared there (MatchCosmics::refitSeedAtTime: TPC refit from the outer parameters, then the propagation to the DCA as for the seeds; energy loss along the muon's flight as in refitWinners). The TPC refitter is created once per TF in process() and shared with refitWinners. The matcher debug tree writes the legs compared and a commonTime flag. Cosmic MC with PbPb-like distortions (190 TFs, preset physics-v1, off -> on): correctly matched muons 6848 -> 7324 of 8639 (79.3 -> 84.8 %); same side 77.0 -> 84.2 %, its loss to the crude chi2 cut 6.9 -> 0.8 %; A×C unchanged; 0 wrong-muon pairs in both; matcher +12 ms per TF (~100 refits). With the true MC time instead of the window centre the same-side pass rate of the chi2 cut would be 99.2 % (centre 98.0 %, legs at their own time0s 84.7 %). PbPb 2025 (4 TFs): ~530 refits per TF, +15 ms per TF. Not in the preset: in PbPb (568041, 310 CTFs, 16541 TFs) it adds mostly pairs of collision tracks, whose time0 was about right and which the refit at the window centre mis-corrects: +352 same-side cosmics but only +5 TOF-tagged (2.6 % of the new ones vs 15.3 % of the common ones), and ~35 A×C cosmics lose a leg to a refitted same-side pair. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * MatchCosmics: TOF flight pair of the legs as selection criterion New MatchCosmicsParams tofFlightSelection (default off, on in the preset physics-v1; needs TOF clusters, the workflow then adds them to the matcher's inputs): every pair of TPC-only legs accepted by checkPair is tested for a top / bottom TOF cluster pair along the outward continuations of its legs whose time difference matches the muon's flight between them along the helix (tofFlightTolerance), with the mean time in the pair's time window and both legs' y and z within tofRoad at that time (the test of the cluster collector). A confirmed pair takes the TOF time as its common time (error tofTimeError), so the winner is refitted at it, and is put in front of all unconfirmed partners of both legs (chi2 order within each group): the mutual-best selection prefers it, and a random pair can no longer take a leg of a TOF-confirmed cosmic. If the refit of a confirmed winner at the TOF time fails (in practice chi2Match > maxChi2Match), it is refitted at the time it has without its TOF flight pair (z-continuity time of legs on opposite sides, else the centre of the overlap of the legs' time brackets): the winner selection has already released the other candidates of both legs, so dropping the winner loses both legs. PbPb 568041: 24 TOF-tagged same-side cosmics, all real (legs on one line far from the beam line, TOF pair in the physical order without a reversed-order alternative), mostly on the C side nearer the readout at the TOF time; A-C cosmics show no TOF-TPC time offset there. The refit loop body is a lambda refitting a winner at a given time. The TOF candidates of a leg are searched once per TF, in the time-sorted TOF clusters of its time bracket and in the sector it points to and its neighbours. Debug tree "match": tofScore. Distorted cosmic MC (19 x 10 TFs, PbPb-like distortions, physics-v1 without the common-time refit, without -> with tofFlightSelection): matched muons 6848 -> 6871 of 8639, 0 wrong pairs both, 2134 confirmed pairs, 9 fallbacks. PbPb 568041 reconstructed from CTF (310 CTFs, 16541 TFs, vs. the same CTFs without the TOF selection, older code, before the fallback): cosmics 4782 -> 4760, TOF-tagged 681 -> 697; A-C: 11 untagged pairings replaced by 12 TOF-tagged ones. Matcher CPU 0.536 -> 0.545 s per TF. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * calib-workflow.sh: optional cosmics matching with raw-cluster output in async With CALIB_ASYNC_EXTRACTCOSMICS=1 (set by O2DPG from the JDL), the async calibration workflows add o2-cosmics-match-workflow on the TPC-only tracks with the preset COSMICS_PRESET (default physics-v1) and the raw-cluster output (o2_cosmics_full.root, always written, as the TPC time series). The road detectors are those of ITS, TOF, TRD reconstructed in the job; without TOF the preset's TOF flight selection is switched off. Checked in print mode with the O2DPG counterpart: the switch adds only this workflow; no workflow without TPC, in sync mode, or with the switch unset. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * DataFormatsGlobalTracking: rename CosmicTrack to TrackCosmicsExtended The per-cosmic output of the cluster collector contains the matcher's TrackCosmics plus the raw hits of its legs; the new name makes that relation explicit (review comment). Header CosmicTrack.h is now TrackCosmicsExtended.h; content and branch names are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * MatchCosmics: legs near the beam line for TOF-confirmed pairs only The seed cuts minSeedDCAxy / minSeedDCAxyNSigma (3 cm / 10 sigma in physics-v1) reject the legs of collision tracks, but also the cosmics crossing the ITS inner barrel (L0 / L1 entirely, L2 mostly). Loosening them floods the matcher with collision-track pairs (PbPb 567939, 600 TFs: 1 cm / 3 sigma gives 38x more candidates, TOF-tagged 0.1 % vs 14 %). New MatchCosmicsParams minSeedDCAxyTOF (default -1: off) and minSeedDCAxyNSigmaTOF (3): with tofFlightSelection, TPC-only legs failing the seed DCA cuts but passing these looser ones are kept, flagged nearBeam, and used in TOF-confirmed pairs only: a pair with such a leg and no TOF flight pair is rejected (RejNoTOF) before it is registered, so it cannot compete in the winner selection or reach the cluster collector. Log line: seeds near the beam line and their confirmed pairs per TF. The cosmics carry TrackCosmics flags NearBeamBottom / NearBeamTop (new member, class version 2) for legs kept only by the looser cuts, so these cosmics can be selected or dropped downstream without redoing the seed cuts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * CosmicsClusterCollector: ITS road keeps the 5 closest clusters per inner-barrel layer Near the beam line the road in the inner barrel is dense with collision clusters, and the TPC prediction there (~mm) does not single out the cosmic's hit: keeping only the closest cluster per half of the cosmic and layer often stores a random one. In layers 0-2 the 5 closest are now kept, best first (the first is the previous choice); the outer barrel keeps the closest. The insertion rejects a NaN score, as the single-hit comparison did. Only cosmics with |DCA_xy| < 3.8 cm cross the inner barrel, so the output grows only for those. PbPb 568041, 400 CTFs with near-beam legs (minSeedDCAxyTOF=0): first road hit of every (cosmic, half, layer) identical to the previous code, outer barrel unchanged, output +1.8 %. On near-beam tracks fitted in the outer barrel, 24 of the 31 inner-barrel hits on the track are not the closest road hit (the ranking is dominated by the z uncertainty). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * MatchCosmics: reject legs that are part of primary-vertex contributors Review suggestion: a TPC track that is part of a global track contributing to a primary vertex comes from a collision, not from a cosmic. The existing veto (--use-pv-info with cosmicsMatch.discardPVContributors, default on) compared the contributor's own track ID with the seeds, so it never fired for TPC-only legs: the contributors are ITS-TPC and higher. New workflow option --pv-contributor-sources (implies --use-pv-info, ignored with a warning if discardPVContributors is off): the contributors of these global track sources reject every leg they contain (RecoContainer::getSingleDetectorRefs), e.g. their TPC track. The sources and the parent matches needed to resolve them are loaded only for this; the legs still come from --track-sources only. Log line: seeds rejected per TF (also those that are themselves contributors). PbPb 567939, 2 TFs with vertices (94 each), sources ITS-TPC,ITS-TPC-TRD, ITS-TPC-TOF,ITS-TPC-TRD-TOF: 54 % of the TPC seeds rejected; without seed DCA cuts the collision-track pairs drop from 183 / 285 to 58 / 88 per TF, with the near-beam option the near-beam seeds by 57 %; matcher CPU for the 4 TFs (2 of them without vertices) 3.1 -> 2.3 s; the physics-v1 cosmic is kept. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * calib-workflow.sh: PV-contributor veto for the cosmics in async With CALIB_ASYNC_EXTRACTCOSMICS=1 the cosmics matcher gets --pv-contributor-sources $VERTEXING_SOURCES when the primary vertexing runs, as the time series gets $TRACK_SOURCES: the TPC part of a vertex contributor is no cosmic leg. COSMICS_PV_VETO=0 switches it off, COSMICS_PV_SOURCES overrides the sources. The option ignores sources without TPC, so the vertexing sources are passed as they are (help text). Checked in print mode (veto on / off, without ITS: TPC-TOF) and on 4 PbPb TFs with the full vertexing source list: the same seeds rejected as with the 4 ITS-TPC sources that have contributors there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Cosmics: load the ITS tracks of legs with an ITS part With --track-sources containing ITS-TPC (or another source with ITS) but not ITS, the matcher's winner refit and the cluster collector read the ITS track of such a leg (getITSTrack, its cluster references), which was neither requested nor read: segfault in refitWinner, then in the collector; without an ITS road there was also no ITS cluster reader (invalid workflow). The ITS tracks and clusters are now requested and read for these legs, without making standalone ITS tracks legs (seed sources unchanged). TPC-only legs (physics-v1 in async) are not affected. PbPb 567939, 4 TFs, --track-sources TPC,ITS-TPC: all TFs processed with and without the ITS road (crash before), no ITS-only legs (seeds 23318 vs 26345 with ITS as legs); TPC-only legs: unchanged, no ITS track reader. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * calib-workflow.sh: CALIB_ASYNC_EXTRACTCOSMICS may be unset The switch is defined (default 0) only by the O2DPG counterpart of the cosmics wiring; with an O2DPG without it every async workflow stopped at the test (unbound variable under set -u). Default to 0 here. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 50d355e commit d24f2c1

21 files changed

Lines changed: 2549 additions & 84 deletions

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/TrackCosmicsExtended.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 TrackCosmicsExtended.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_TRACK_COSMICS_EXTENDED_H
16+
#define ALICEO2_TRACK_COSMICS_EXTENDED_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: TrackCosmicsExtended::timeTOFMUS
36+
///< if >= 0, else the time of TrackCosmicsExtended::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 TrackCosmicsExtended::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 TrackCosmicsExtended {
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 (per half and layer the closest, in the inner barrel up to 5, best first)
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(TrackCosmicsExtended, 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::TrackCosmicsExtended + ;
34+
#pragma link C++ class std::vector < o2::dataformats::TrackCosmicsExtended> + ;
35+
#pragma link C++ class o2::dataformats::CosmicsTFInfo + ;
36+
2537
#endif

‎DataFormats/Reconstruction/include/ReconstructionDataFormats/TrackCosmics.h‎

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ class TrackCosmics : public o2::track::TrackParCov
3030
using timeEst = o2::dataformats::TimeStampWithError<float, float>;
3131

3232
public:
33+
enum Flags : uint8_t {
34+
NearBeamBottom = 0x1, ///< bottom leg failed the standard seed DCA cuts (close to the beam line, absolutely or within its errors) and
35+
///< passed only the looser minSeedDCAxyTOF ones (TOF-confirmed pairs only)
36+
NearBeamTop = 0x2 ///< the same for the top leg
37+
};
38+
3339
TrackCosmics() = default;
3440
~TrackCosmics() = default;
3541
TrackCosmics(const TrackCosmics& src) = default;
@@ -59,6 +65,10 @@ class TrackCosmics : public o2::track::TrackParCov
5965
int getNClusters() const { return mNClusters; }
6066
void setNClusters(int n) { mNClusters = n; }
6167

68+
uint8_t getFlags() const { return mFlags; }
69+
void setFlags(uint8_t flags) { mFlags = flags; }
70+
bool isNearBeam() const { return mFlags & (NearBeamBottom | NearBeamTop); }
71+
6272
o2::track::TrackParCov& getParamOut() { return mParamOut; }
6373
const o2::track::TrackParCov& getParamOut() const { return mParamOut; }
6474

@@ -72,8 +82,9 @@ class TrackCosmics : public o2::track::TrackParCov
7282
int mNClusters = 0; ///< total number of fitted clusters
7383
timeEst mTimeMUS; ///< time estimate in ns
7484
o2::track::TrackParCov mParamOut; ///< refitted outer parameter
85+
uint8_t mFlags = 0; ///< Flags: NearBeamBottom, NearBeamTop
7586

76-
ClassDefNV(TrackCosmics, 1);
87+
ClassDefNV(TrackCosmics, 2);
7788
};
7889
} // namespace dataformats
7990
} // namespace o2

‎Detectors/GlobalTracking/include/GlobalTracking/MatchCosmics.h‎

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#define ALICEO2_MATCH_COSMICS
1818

1919
#include <Rtypes.h>
20+
#include <array>
21+
#include <cstdint>
2022
#include <MathUtils/Primitive2D.h>
2123
#include "ReconstructionDataFormats/TrackCosmics.h"
2224
#include "ReconstructionDataFormats/GlobalTrackID.h"
@@ -39,7 +41,8 @@ class VDriftCorrFact;
3941
namespace gpu
4042
{
4143
class TPCFastTransformPOD;
42-
}
44+
class GPUO2InterfaceRefit;
45+
} // namespace gpu
4346
namespace globaltracking
4447
{
4548

@@ -67,7 +70,9 @@ class MatchCosmics
6770
RejTime,
6871
RejProp,
6972
RejChi2,
70-
RejOther
73+
RejOther,
74+
RejSameHalf,
75+
RejNoTOF ///< a leg kept by minSeedDCAxyTOF only, and no TOF flight pair
7176
};
7277

7378
using InfoAccessor = o2d::AbstractRefAccessor<int, GTrackID::NSources>; // there is no unique <Info> structure, so the default return type is dummy (int)
@@ -78,6 +83,21 @@ class MatchCosmics
7883
int id1 = MinusOne; ///< id of 2nd parnter
7984
float chi2 = -1.f; ///< matching chi2
8085
int next = MinusOne; ///< index of eventual next record
86+
float tCommon = 0.f; ///< common time [mus] fixed by z continuity of TPC-only legs on opposite TPC sides
87+
float tCommonErr = -1.f; ///< its 1 sigma error [mus]; < 0: not fixed, the refit uses the centre of the time-bracket overlap and the cosmic's time error is the overlap's half-width
88+
float tofScore = -1.f; ///< score of the top / bottom TOF hit pair matching the muon's flight (tofFlightSelection; < 0: none); a pair with one wins against pairs without
89+
float tCommonNoTOF = 0.f; ///< tCommon before a TOF flight pair replaced it: the refit falls back to it if the refit at the TOF time fails
90+
float tCommonErrNoTOF = -1.f; ///< tCommonErr before a TOF flight pair replaced it
91+
};
92+
93+
struct TOFCandidate { ///< TOF cluster along the outward continuation of a TPC-only seed
94+
int index = -1; ///< index of the TOF cluster
95+
double timeNS = 0.; ///< its time since the start of the TF [ns]
96+
float dy = 0.f; ///< cluster - predicted y in the frame of the cluster's sector [cm]
97+
float dz = 0.f; ///< cluster - predicted z, the leg's z taken at its own reference time tRef [cm]
98+
float gx = 0.f; ///< global position of the cluster [cm]
99+
float gy = 0.f;
100+
float gz = 0.f;
81101
};
82102

83103
struct TrackSeed : public o2::track::TrackParCov {
@@ -86,6 +106,10 @@ class MatchCosmics
86106
int matchID = MinusOne; ///< entry (none if MinusOne) of its match in the vector of matches
87107
short vtIDMin = -1; ///< id of the 1st compatible vertex
88108
short vtIDMax = -1; ///< id of the last compatible vertex
109+
float tRef = 0.f; ///< time [mus] the z of the parameters refers to (TPC-only: the TrackTPC time0; others: bracket centre)
110+
int8_t tpcSide = 0; ///< TPC-only seed with clusters on one side: +1 A, -1 C (z = z(t) - side*vD*(t-tRef)); 0: z absolute
111+
std::array<float, 3> xyzRef{}; ///< global position of the reference point before the propagation to the DCA (same-half veto)
112+
bool nearBeam = false; ///< kept by the looser minSeedDCAxyTOF cuts only: usable in TOF-confirmed pairs only
89113
};
90114
void setTPCCorrMaps(const o2::gpu::TPCFastTransformPOD* maph);
91115
void setTPCVDrift(const o2::tpc::VDriftCorrFact& v);
@@ -94,6 +118,8 @@ class MatchCosmics
94118
void process(const o2::globaltracking::RecoContainer& data);
95119
void setUseMC(bool mc) { mUseMC = mc; }
96120
void setUsePVInfo(bool v) { mUsePVInfo = v; }
121+
void setSeedSources(GTrackID::mask_t src) { mSeedSources = src; } ///< track sources used as legs (other loaded ones resolve PV contributors)
122+
void setPVVetoSources(GTrackID::mask_t src) { mPVVetoSources = src; } ///< sources whose PV contributors veto the legs they contain
97123
void init();
98124
void end();
99125

@@ -129,7 +155,11 @@ class MatchCosmics
129155
private:
130156
void updateTimeDependentParams();
131157
RejFlag checkPair(int i, int j);
132-
void registerMatch(int i, int j, float chi2);
158+
bool refitSeedAtTime(const TrackSeed& seed, float timeMUS, TrackSeed& out);
159+
void registerMatch(int i, int j, float chi2, float tCommon = 0.f, float tCommonErr = -1.f, float tofScore = -1.f, float tCommonNoTOF = 0.f, float tCommonErrNoTOF = -1.f);
160+
void prepareTOFClusters(const o2::globaltracking::RecoContainer& data);
161+
const std::vector<TOFCandidate>& getTOFCandidates(int iseed);
162+
float findTOFFlightPair(int i, int j, float tMinMUS, float tMaxMUS, float& tofTimeMUS);
133163
void suppressMatch(int partner0, int partner1);
134164
void createSeeds(const o2::globaltracking::RecoContainer& data);
135165
bool validateMatch(int partner0);
@@ -152,9 +182,24 @@ class MatchCosmics
152182
bool mFieldON = true;
153183
bool mUsePVInfo = false;
154184
bool mUseMC = true;
185+
GTrackID::mask_t mSeedSources{GTrackID::MASK_ALL}; ///< track sources used as legs
186+
GTrackID::mask_t mPVVetoSources{GTrackID::MASK_NONE}; ///< sources whose PV contributors veto the legs they contain
155187
float mITSROFrameLengthMUS = 0.;
156188
float mQ2PtCutoff = 1e9;
189+
float mQ2PtCutoffOppositeSides = 1e9;
157190
const MatchCosmicsParams* mMatchParams = nullptr;
191+
const o2::globaltracking::RecoContainer* mRecoData = nullptr; ///< inputs of the TF being processed
192+
o2::gpu::GPUO2InterfaceRefit* mTPCRefitter = nullptr; ///< TPC refitter of the TF being processed (owned by process())
193+
size_t mNRefitsCommonTime = 0; ///< seeds refitted at the common time of a same-side pair in this TF
194+
std::vector<int> mTOFClusterOrder; ///< TOF clusters of the TF sorted in time (tofFlightSelection)
195+
std::vector<float> mTOFClusterTimeMUS; ///< their times since the start of the TF [mus], same order
196+
std::vector<std::vector<TOFCandidate>> mSeedTOFCandidates; ///< TOF candidates per seed, filled on first use
197+
std::vector<bool> mSeedTOFDone; ///< the TOF candidates of the seed are filled
198+
size_t mNTOFConfirmed = 0; ///< accepted pairs with a TOF flight pair in this TF
199+
size_t mNTOFFallbacks = 0; ///< TOF-confirmed winners refitted at their time without TOF in this TF
200+
size_t mNSeedsNearBeam = 0; ///< TPC-only seeds kept for TOF-confirmed pairs only (minSeedDCAxyTOF) in this TF
201+
size_t mNNearBeamConfirmed = 0; ///< accepted pairs with such a seed, confirmed by a TOF flight pair, in this TF
202+
size_t mNSeedsPVContributors = 0; ///< seeds rejected as part of a primary-vertex contributor in this TF
158203

159204
std::vector<o2d::TrackCosmics> mCosmicTracks;
160205
std::vector<o2::MCCompLabel> mCosmicTracksLbl;

0 commit comments

Comments
 (0)