Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
14 commits
Select commit Hold shift + click to select a range
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
51 changes: 48 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 All @@ -94,6 +118,8 @@ class MatchCosmics
void process(const o2::globaltracking::RecoContainer& data);
void setUseMC(bool mc) { mUseMC = mc; }
void setUsePVInfo(bool v) { mUsePVInfo = v; }
void setSeedSources(GTrackID::mask_t src) { mSeedSources = src; } ///< track sources used as legs (other loaded ones resolve PV contributors)
void setPVVetoSources(GTrackID::mask_t src) { mPVVetoSources = src; } ///< sources whose PV contributors veto the legs they contain
void init();
void end();

Expand Down Expand Up @@ -129,7 +155,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 @@ -152,9 +182,24 @@ class MatchCosmics
bool mFieldON = true;
bool mUsePVInfo = false;
bool mUseMC = true;
GTrackID::mask_t mSeedSources{GTrackID::MASK_ALL}; ///< track sources used as legs
GTrackID::mask_t mPVVetoSources{GTrackID::MASK_NONE}; ///< sources whose PV contributors veto the legs they contain
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
size_t mNSeedsPVContributors = 0; ///< seeds rejected as part of a primary-vertex contributor in this TF

std::vector<o2d::TrackCosmics> mCosmicTracks;
std::vector<o2::MCCompLabel> mCosmicTracksLbl;
Expand Down
Loading
Loading