Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions DataFormats/Detectors/GlobalTracking/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,5 @@ o2_target_root_dictionary(
DataFormatsGlobalTracking
HEADERS include/DataFormatsGlobalTracking/FilteredRecoTF.h
include/DataFormatsGlobalTracking/TrackTuneParams.h
include/DataFormatsGlobalTracking/TrackCosmicsExtended.h
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Copyright 2019-2026 CERN and copyright holders of ALICE O2.
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
// All rights not expressly granted are reserved.
//
// This software is distributed under the terms of the GNU General Public
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
//
// In applying this license CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.

/// \file TrackCosmicsExtended.h
/// \brief Matched cosmic track with the raw clusters of its legs and of the road around them, for offline refits

#ifndef ALICEO2_TRACK_COSMICS_EXTENDED_H
#define ALICEO2_TRACK_COSMICS_EXTENDED_H

#include <vector>
#include <cstdint>
#include <Rtypes.h>
#include "ReconstructionDataFormats/TrackCosmics.h"
#include "DataFormatsTPC/TrackTPC.h"
#include "DataFormatsTPC/ClusterNative.h"
#include "SimulationDataFormat/MCCompLabel.h"

namespace o2::dataformats
{

/// raw TPC cluster with its address; transformed coordinates are not stored (re-transform offline with the calibration of the TF)
struct CosmicTPCCluster {
enum Flags : uint8_t {
Attached = 0x1, ///< attached to the TPC track of this leg
Corridor = 0x2, ///< found in the road around the leg
Used = 0x4, ///< attached to some TPC track (for corridor clusters: another track, e.g. a split piece of the leg)
AbsTime = 0x8 ///< found on the other TPC side with the absolute time of the cosmic instead of the time0 of the leg: TrackCosmicsExtended::timeTOFMUS
///< if >= 0, else the time of TrackCosmicsExtended::cosmic
};
o2::tpc::ClusterNative cl{}; ///< raw cluster: time, pad, widths, charges, flags
uint8_t sector = 0;
uint8_t row = 0;
uint8_t flags = 0;
bool isAttached() const { return flags & Attached; }
bool isCorridor() const { return flags & Corridor; }
bool isUsed() const { return flags & Used; }
bool isAbsTime() const { return flags & AbsTime; }
ClassDefNV(CosmicTPCCluster, 1);
};

/// origin of the ITS / TOF / TRD hits of a cosmic
enum CosmicHitFlags : uint8_t {
HitMatched = 0x1, ///< part of the leg's matched global track
HitRoad = 0x2, ///< found by the road search around the cosmic
HitTOFFlight = 0x4 ///< TOF road hit of the top/bottom pair whose time difference matches the muon's flight (fixes the cosmic's time)
};

/// ITS cluster of a leg: the raw compact cluster (chip, anchor pixel, pattern ID) and its ROF; no coordinates (the dictionary and the
/// geometry are applied offline)
struct CosmicITSCluster {
uint16_t chipID = 0;
uint16_t row = 0;
uint16_t col = 0;
uint16_t pattID = 0;
int32_t pattEntry = -1; ///< start of the pattern bytes in TrackCosmicsExtended::itsPatterns (pattern not in the dictionary or group pattern), -1: none
int32_t rofBC = 0; ///< start of the cluster's ROF in BCs since the start of the TF
uint8_t leg = 0; ///< 0 bottom, 1 top
uint8_t flags = 0; ///< CosmicHitFlags
ClassDefNV(CosmicITSCluster, 1);
};

/// TOF cluster of a leg: matched to its track or found on the road
struct CosmicTOFCluster {
double timeRaw = 0.; ///< raw TOF time [ps] (the calibration is applied offline)
float tot = 0.f; ///< time over threshold
int32_t channel = -1;
uint8_t leg = 0;
uint8_t flags = 0; ///< CosmicHitFlags
ClassDefNV(CosmicTOFCluster, 1);
};

/// TRD tracklet of a leg: attached to its track or found on the road
struct CosmicTRDTracklet {
uint64_t word = 0; ///< raw Tracklet64 word
int32_t trigBC = 0; ///< BC of its trigger since the start of the TF
uint8_t layer = 0;
uint8_t leg = 0;
uint8_t flags = 0; ///< CosmicHitFlags
ClassDefNV(CosmicTRDTracklet, 1);
};

/// matched cosmic with everything needed for an offline refit
struct TrackCosmicsExtended {
o2::dataformats::TrackCosmics cosmic{}; ///< matcher output (time in mus; the leg references are only valid within the TF)
o2::tpc::TrackTPC tpcBottom{}; ///< TPC part of the bottom leg (default if none); z refers to its time0; its cluster
///< references are only valid within the TF: the clusters are in clTPCBottom
o2::tpc::TrackTPC tpcTop{}; ///< TPC part of the top leg
std::vector<CosmicTPCCluster> clTPCBottom; ///< attached + corridor TPC clusters of the bottom leg
std::vector<CosmicTPCCluster> clTPCTop; ///< same for the top leg
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)
std::vector<uint8_t> itsPatterns; ///< pattern bytes (row span, column span, bitmap) of the ITS clusters that need them
std::vector<CosmicTOFCluster> clTOF; ///< TOF clusters of the legs' matched tracks and on the road
std::vector<CosmicTRDTracklet> trdTracklets; ///< TRD tracklets of the legs' matched tracks and on the road
float timeTOFMUS = -1.f; ///< time of the cosmic [mus since the TF start, negative before it] from its HitTOFFlight pair (valid if hasTOFTime())
float scoreTOFPair = -1.f; ///< score of the HitTOFFlight pair: road and flight-time residuals squared in units of the cuts (< 0: none)
float scoreTOFReversed = -1.f; ///< same for the best pair in the impossible order (bottom hit first) = an accidental coincidence:
///< QA of the flag's background; comparable to scoreTOFPair = ambiguous TOF time (< 0: none)
int duplicateOf = -1; ///< entry (in the TF) of the cosmic this one duplicates: the same muon matched twice (e.g. a leg split
///< into two TPC tracks): >= 30 % of the smaller one's TPC clusters shared with a better one (TOF time,
///< more attached clusters) (-1: none)
o2::track::TrackParCov polished{}; ///< refit at the TOF time (TPC-only legs, muon mass, energy loss along the flight), at the closest
///< approach to the beam line; valid if chi2MatchPolished >= 0
float chi2MatchPolished = -1.f; ///< chi2 of the polished bottom and top halves at the closest approach (< 0: not polished)
o2::MCCompLabel label{}; ///< MC label of the cosmic (MC only)

bool hasTOFTime() const { return scoreTOFPair >= 0.f; } ///< a HitTOFFlight pair gave the cosmic its time timeTOFMUS
ClassDefNV(TrackCosmicsExtended, 1);
};

/// per-TF quantities of the TPC transformation used in the reconstruction
struct CosmicsTFInfo {
float vDrift = 0.f; ///< drift velocity of the transformation [cm/time bin]
float t0 = 0.f; ///< time offset of the transformation [time bins]
ClassDefNV(CosmicsTFInfo, 1);
};

} // namespace o2::dataformats

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,16 @@
#pragma link C++ class o2::globaltracking::TrackTuneParams + ;
#pragma link C++ class o2::conf::ConfigurableParamHelper < o2::globaltracking::TrackTuneParams> + ;

#pragma link C++ class o2::dataformats::CosmicTPCCluster + ;
#pragma link C++ class std::vector < o2::dataformats::CosmicTPCCluster> + ;
#pragma link C++ class o2::dataformats::CosmicITSCluster + ;
#pragma link C++ class std::vector < o2::dataformats::CosmicITSCluster> + ;
#pragma link C++ class o2::dataformats::CosmicTOFCluster + ;
#pragma link C++ class std::vector < o2::dataformats::CosmicTOFCluster> + ;
#pragma link C++ class o2::dataformats::CosmicTRDTracklet + ;
#pragma link C++ class std::vector < o2::dataformats::CosmicTRDTracklet> + ;
#pragma link C++ class o2::dataformats::TrackCosmicsExtended + ;
#pragma link C++ class std::vector < o2::dataformats::TrackCosmicsExtended> + ;
#pragma link C++ class o2::dataformats::CosmicsTFInfo + ;

#endif
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ class TrackCosmics : public o2::track::TrackParCov
using timeEst = o2::dataformats::TimeStampWithError<float, float>;

public:
enum Flags : uint8_t {
NearBeamBottom = 0x1, ///< bottom leg failed the standard seed DCA cuts (close to the beam line, absolutely or within its errors) and
///< passed only the looser minSeedDCAxyTOF ones (TOF-confirmed pairs only)
NearBeamTop = 0x2 ///< the same for the top leg
};

TrackCosmics() = default;
~TrackCosmics() = default;
TrackCosmics(const TrackCosmics& src) = default;
Expand Down Expand Up @@ -59,6 +65,10 @@ class TrackCosmics : public o2::track::TrackParCov
int getNClusters() const { return mNClusters; }
void setNClusters(int n) { mNClusters = n; }

uint8_t getFlags() const { return mFlags; }
void setFlags(uint8_t flags) { mFlags = flags; }
bool isNearBeam() const { return mFlags & (NearBeamBottom | NearBeamTop); }

o2::track::TrackParCov& getParamOut() { return mParamOut; }
const o2::track::TrackParCov& getParamOut() const { return mParamOut; }

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

ClassDefNV(TrackCosmics, 1);
ClassDefNV(TrackCosmics, 2);
};
} // namespace dataformats
} // namespace o2
Expand Down
46 changes: 43 additions & 3 deletions Detectors/GlobalTracking/include/GlobalTracking/MatchCosmics.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
#define ALICEO2_MATCH_COSMICS

#include <Rtypes.h>
#include <array>
#include <cstdint>
#include <MathUtils/Primitive2D.h>
#include "ReconstructionDataFormats/TrackCosmics.h"
#include "ReconstructionDataFormats/GlobalTrackID.h"
Expand All @@ -39,7 +41,8 @@ class VDriftCorrFact;
namespace gpu
{
class TPCFastTransformPOD;
}
class GPUO2InterfaceRefit;
} // namespace gpu
namespace globaltracking
{

Expand Down Expand Up @@ -67,7 +70,9 @@ class MatchCosmics
RejTime,
RejProp,
RejChi2,
RejOther
RejOther,
RejSameHalf,
RejNoTOF ///< a leg kept by minSeedDCAxyTOF only, and no TOF flight pair
};

using InfoAccessor = o2d::AbstractRefAccessor<int, GTrackID::NSources>; // there is no unique <Info> structure, so the default return type is dummy (int)
Expand All @@ -78,6 +83,21 @@ class MatchCosmics
int id1 = MinusOne; ///< id of 2nd parnter
float chi2 = -1.f; ///< matching chi2
int next = MinusOne; ///< index of eventual next record
float tCommon = 0.f; ///< common time [mus] fixed by z continuity of TPC-only legs on opposite TPC sides
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
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
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
float tCommonErrNoTOF = -1.f; ///< tCommonErr before a TOF flight pair replaced it
};

struct TOFCandidate { ///< TOF cluster along the outward continuation of a TPC-only seed
int index = -1; ///< index of the TOF cluster
double timeNS = 0.; ///< its time since the start of the TF [ns]
float dy = 0.f; ///< cluster - predicted y in the frame of the cluster's sector [cm]
float dz = 0.f; ///< cluster - predicted z, the leg's z taken at its own reference time tRef [cm]
float gx = 0.f; ///< global position of the cluster [cm]
float gy = 0.f;
float gz = 0.f;
};

struct TrackSeed : public o2::track::TrackParCov {
Expand All @@ -86,6 +106,10 @@ class MatchCosmics
int matchID = MinusOne; ///< entry (none if MinusOne) of its match in the vector of matches
short vtIDMin = -1; ///< id of the 1st compatible vertex
short vtIDMax = -1; ///< id of the last compatible vertex
float tRef = 0.f; ///< time [mus] the z of the parameters refers to (TPC-only: the TrackTPC time0; others: bracket centre)
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
std::array<float, 3> xyzRef{}; ///< global position of the reference point before the propagation to the DCA (same-half veto)
bool nearBeam = false; ///< kept by the looser minSeedDCAxyTOF cuts only: usable in TOF-confirmed pairs only
};
void setTPCCorrMaps(const o2::gpu::TPCFastTransformPOD* maph);
void setTPCVDrift(const o2::tpc::VDriftCorrFact& v);
Expand Down Expand Up @@ -129,7 +153,11 @@ class MatchCosmics
private:
void updateTimeDependentParams();
RejFlag checkPair(int i, int j);
void registerMatch(int i, int j, float chi2);
bool refitSeedAtTime(const TrackSeed& seed, float timeMUS, TrackSeed& out);
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);
void prepareTOFClusters(const o2::globaltracking::RecoContainer& data);
const std::vector<TOFCandidate>& getTOFCandidates(int iseed);
float findTOFFlightPair(int i, int j, float tMinMUS, float tMaxMUS, float& tofTimeMUS);
void suppressMatch(int partner0, int partner1);
void createSeeds(const o2::globaltracking::RecoContainer& data);
bool validateMatch(int partner0);
Expand All @@ -154,7 +182,19 @@ class MatchCosmics
bool mUseMC = true;
float mITSROFrameLengthMUS = 0.;
float mQ2PtCutoff = 1e9;
float mQ2PtCutoffOppositeSides = 1e9;
const MatchCosmicsParams* mMatchParams = nullptr;
const o2::globaltracking::RecoContainer* mRecoData = nullptr; ///< inputs of the TF being processed
o2::gpu::GPUO2InterfaceRefit* mTPCRefitter = nullptr; ///< TPC refitter of the TF being processed (owned by process())
size_t mNRefitsCommonTime = 0; ///< seeds refitted at the common time of a same-side pair in this TF
std::vector<int> mTOFClusterOrder; ///< TOF clusters of the TF sorted in time (tofFlightSelection)
std::vector<float> mTOFClusterTimeMUS; ///< their times since the start of the TF [mus], same order
std::vector<std::vector<TOFCandidate>> mSeedTOFCandidates; ///< TOF candidates per seed, filled on first use
std::vector<bool> mSeedTOFDone; ///< the TOF candidates of the seed are filled
size_t mNTOFConfirmed = 0; ///< accepted pairs with a TOF flight pair in this TF
size_t mNTOFFallbacks = 0; ///< TOF-confirmed winners refitted at their time without TOF in this TF
size_t mNSeedsNearBeam = 0; ///< TPC-only seeds kept for TOF-confirmed pairs only (minSeedDCAxyTOF) in this TF
size_t mNNearBeamConfirmed = 0; ///< accepted pairs with such a seed, confirmed by a TOF flight pair, in this TF

std::vector<o2d::TrackCosmics> mCosmicTracks;
std::vector<o2::MCCompLabel> mCosmicTracksLbl;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "CommonUtils/ConfigurableParamHelper.h"
#include "DetectorsBase/Propagator.h"
#include "ReconstructionDataFormats/GlobalTrackID.h"
#include <string>

namespace o2
{
Expand All @@ -29,10 +30,24 @@ struct MatchCosmicsParams : public o2::conf::ConfigurableParamHelper<MatchCosmic
float systSigma2[o2::track::kNParams] = {0.01f, 0.01f, 1e-4f, 1e-4f, 0.f}; // extra error to be added at legs comparison
float crudeNSigma2Cut[o2::track::kNParams] = {49.f, 49.f, 49.f, 49.f, 49.f};
float crudeChi2Cut = 999.f;
float maxChi2Match = -1.f; // reject cosmics whose top/bottom refitted legs disagree by more than this chi2 (< 0: no cut)
float minPtOppositeSides = 0.f; // TPC-only legs on opposite TPC sides: reject cosmics with the pT of either leg or of the refitted cosmic below this (scaled with field; 0: no cut)
float timeToleranceMUS = 0.f;
float maxStep = 10.f;
float maxSnp = 0.99f;
float minSeedPt = 0.10f; // use only tracks above this pT (scaled with field)
int minSeedNClTPC = 0; // use only TPC-only seeds with at least this number of clusters (0: no cut)
float minSeedDCAxy = 0.f; // use only tracks with |DCA_xy| to the beam line >= this [cm] (0: no cut; rejects collision tracks in physics data)
float minSeedDCAxyNSigma = 0.f; // use only tracks with |DCA_xy| >= this * sigma(DCA_xy) (0: no cut; poorly measured collision tracks)
float minSeedDCAxyTOF = -1.f; // with tofFlightSelection: TPC-only legs failing the two cuts above but with |DCA_xy| >= this [cm] are used in TOF-confirmed pairs only (< 0: off; e.g. cosmics crossing the ITS inner barrel)
float minSeedDCAxyNSigmaTOF = 3.f; // the same for these legs in units of sigma(DCA_xy)
bool constrainTPCOnlyZ = false; // TPC-only legs: test z at a common time (same side, or a leg with known time), else require the time implied by z continuity in both brackets
bool vetoSameHalf = false; // reject pairs whose two legs lie on the same side of the closest approach (two pieces of one leg)
bool refitSameSideAtCommonTime = false; // TPC-only legs on the same side: compare them refitted at the centre of their brackets' overlap instead of at their own time0s
bool tofFlightSelection = false; // needs TOF clusters: accepted pairs of TPC-only legs pointing to a top / bottom TOF hit pair with the muon's flight time win the selection, refit at that time (if that fails, at their time without TOF)
float tofRoad = 5.f; // half-width [cm] in y and z of the road at the TOF around the outward continuation of a TPC-only leg
float tofFlightTolerance = 2.f; // max. deviation [ns] of the top / bottom TOF time difference from the flight time along the helix
float tofTimeError = 0.1f; // error [mus] of the TOF time of a confirmed cosmic, for its refit and time window (covers TPC vs TOF offsets)
float nSigmaTError = 4.f; // number of sigmas on track time error for matching (except for TPC which provides an interval)
float tpcExtraZError2 = 1.f; // extra error^2 on the TPC-only track Z coordinate
float fiducialRIP = 1.0f; // consider track having |Y@x=0|< this as passing DCA cut (if requested)
Expand All @@ -44,6 +59,12 @@ struct MatchCosmicsParams : public o2::conf::ConfigurableParamHelper<MatchCosmic
O2ParamDef(MatchCosmicsParams, "cosmicsMatch");
};

/// key=value string (configKeyValues syntax) of a named set of MatchCosmicsParams settings; the cosmics-match workflow applies it before
/// --configKeyValues, so single keys can still be overridden. Unknown names are fatal.
/// "physics-v1": cosmics in collision data (seed cuts against collision tracks, realistic systematic errors for the pair chi2, tgl window,
/// pT cut on pairs of TPC-only legs on opposite TPC sides)
std::string getMatchCosmicsPreset(const std::string& name);

} // namespace globaltracking
} // end namespace o2

Expand Down
Loading
Loading