Skip to content

Commit 1472e6a

Browse files
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>
1 parent a2f1d7e commit 1472e6a

5 files changed

Lines changed: 172 additions & 15 deletions

File tree

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

Lines changed: 11 additions & 2 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"
@@ -67,7 +69,8 @@ class MatchCosmics
6769
RejTime,
6870
RejProp,
6971
RejChi2,
70-
RejOther
72+
RejOther,
73+
RejSameHalf
7174
};
7275

7376
using InfoAccessor = o2d::AbstractRefAccessor<int, GTrackID::NSources>; // there is no unique <Info> structure, so the default return type is dummy (int)
@@ -78,6 +81,8 @@ class MatchCosmics
7881
int id1 = MinusOne; ///< id of 2nd parnter
7982
float chi2 = -1.f; ///< matching chi2
8083
int next = MinusOne; ///< index of eventual next record
84+
float tCommon = 0.f; ///< common time [mus] fixed by z continuity of TPC-only legs on opposite TPC sides
85+
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
8186
};
8287

8388
struct TrackSeed : public o2::track::TrackParCov {
@@ -86,6 +91,9 @@ class MatchCosmics
8691
int matchID = MinusOne; ///< entry (none if MinusOne) of its match in the vector of matches
8792
short vtIDMin = -1; ///< id of the 1st compatible vertex
8893
short vtIDMax = -1; ///< id of the last compatible vertex
94+
float tRef = 0.f; ///< time [mus] the z of the parameters refers to (TPC-only: the TrackTPC time0; others: bracket centre)
95+
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
96+
std::array<float, 3> xyzRef{}; ///< global position of the reference point before the propagation to the DCA (same-half veto)
8997
};
9098
void setTPCCorrMaps(const o2::gpu::TPCFastTransformPOD* maph);
9199
void setTPCVDrift(const o2::tpc::VDriftCorrFact& v);
@@ -129,7 +137,7 @@ class MatchCosmics
129137
private:
130138
void updateTimeDependentParams();
131139
RejFlag checkPair(int i, int j);
132-
void registerMatch(int i, int j, float chi2);
140+
void registerMatch(int i, int j, float chi2, float tCommon = 0.f, float tCommonErr = -1.f);
133141
void suppressMatch(int partner0, int partner1);
134142
void createSeeds(const o2::globaltracking::RecoContainer& data);
135143
bool validateMatch(int partner0);
@@ -154,6 +162,7 @@ class MatchCosmics
154162
bool mUseMC = true;
155163
float mITSROFrameLengthMUS = 0.;
156164
float mQ2PtCutoff = 1e9;
165+
float mQ2PtCutoffOppositeSides = 1e9;
157166
const MatchCosmicsParams* mMatchParams = nullptr;
158167

159168
std::vector<o2d::TrackCosmics> mCosmicTracks;

‎Detectors/GlobalTracking/include/GlobalTracking/MatchCosmicsParams.h‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "CommonUtils/ConfigurableParamHelper.h"
1919
#include "DetectorsBase/Propagator.h"
2020
#include "ReconstructionDataFormats/GlobalTrackID.h"
21+
#include <string>
2122

2223
namespace o2
2324
{
@@ -29,10 +30,17 @@ struct MatchCosmicsParams : public o2::conf::ConfigurableParamHelper<MatchCosmic
2930
float systSigma2[o2::track::kNParams] = {0.01f, 0.01f, 1e-4f, 1e-4f, 0.f}; // extra error to be added at legs comparison
3031
float crudeNSigma2Cut[o2::track::kNParams] = {49.f, 49.f, 49.f, 49.f, 49.f};
3132
float crudeChi2Cut = 999.f;
33+
float maxChi2Match = -1.f; // reject cosmics whose top/bottom refitted legs disagree by more than this chi2 (< 0: no cut)
34+
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)
3235
float timeToleranceMUS = 0.f;
3336
float maxStep = 10.f;
3437
float maxSnp = 0.99f;
3538
float minSeedPt = 0.10f; // use only tracks above this pT (scaled with field)
39+
int minSeedNClTPC = 0; // use only TPC-only seeds with at least this number of clusters (0: no cut)
40+
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)
41+
float minSeedDCAxyNSigma = 0.f; // use only tracks with |DCA_xy| >= this * sigma(DCA_xy) (0: no cut; poorly measured collision tracks)
42+
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
43+
bool vetoSameHalf = false; // reject pairs whose two legs lie on the same side of the closest approach (two pieces of one leg)
3644
float nSigmaTError = 4.f; // number of sigmas on track time error for matching (except for TPC which provides an interval)
3745
float tpcExtraZError2 = 1.f; // extra error^2 on the TPC-only track Z coordinate
3846
float fiducialRIP = 1.0f; // consider track having |Y@x=0|< this as passing DCA cut (if requested)
@@ -44,6 +52,12 @@ struct MatchCosmicsParams : public o2::conf::ConfigurableParamHelper<MatchCosmic
4452
O2ParamDef(MatchCosmicsParams, "cosmicsMatch");
4553
};
4654

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

‎Detectors/GlobalTracking/src/MatchCosmics.cxx‎

Lines changed: 109 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,11 @@ void MatchCosmics::process(const o2::globaltracking::RecoContainer& data)
6868
trc.matchID = Reject; // reject track
6969
continue;
7070
}
71+
if (std::abs(trc.getY()) < mMatchParams->minSeedDCAxy || trc.getY() * trc.getY() < mMatchParams->minSeedDCAxyNSigma * mMatchParams->minSeedDCAxyNSigma * trc.getSigmaY2()) {
72+
// passes close to the beam line, absolutely or within its errors: indistinguishable from collision tracks
73+
trc.matchID = Reject;
74+
continue;
75+
}
7176
if (mMatchParams->dcaCutChi2[trc.origID.getSource()] > 0.f && mUsePVInfo && trc.vtIDMin >= 0 && (std::abs(trc.getY()) < mMatchParams->fiducialRIP && std::abs(trc.getZ()) < mMatchParams->fiducialZIP)) {
7277
// do the propagation only if we are in the fiducial IP range.
7378
for (int iv = trc.vtIDMin; iv <= trc.vtIDMax; iv++) { // vtIDMax is the last compatible vertex (inclusive); vtIDMin < 0: no compatible vertex
@@ -180,9 +185,16 @@ void MatchCosmics::refitWinners(const o2::globaltracking::RecoContainer& data)
180185
for (auto winRID : mWinners) {
181186
const auto& rec = mRecords[winRID];
182187
int poolEntryID[2] = {rec.id0, rec.id1};
183-
const o2::track::TrackParCov outerLegs[2] = {data.getTrackParamOut(mSeeds[rec.id0].origID), data.getTrackParamOut(mSeeds[rec.id1].origID)};
188+
o2::track::TrackParCov outerLegs[2] = {data.getTrackParamOut(mSeeds[rec.id0].origID), data.getTrackParamOut(mSeeds[rec.id1].origID)};
189+
for (auto& leg : outerLegs) {
190+
leg.setPID(o2::track::PID::Muon, true); // as the seeds
191+
}
184192
auto tOverlap = mSeeds[rec.id0].tBracket.getOverlap(mSeeds[rec.id1].tBracket);
185193
float t0 = tOverlap.mean(), dt = tOverlap.delta() * 0.5;
194+
if (rec.tCommonErr >= 0.f) { // TPC-only legs on opposite sides: their z continuity fixes the time, refit both legs with it
195+
t0 = rec.tCommon;
196+
dt = rec.tCommonErr;
197+
}
186198
auto pnt0 = outerLegs[0].getXYZGlo(), pnt1 = outerLegs[1].getXYZGlo();
187199
int btm = 0, top = 1;
188200
// we fit topward from bottom
@@ -304,10 +316,19 @@ void MatchCosmics::refitWinners(const o2::globaltracking::RecoContainer& data)
304316
// calculate weighted average of 2 legs and chi2
305317
o2::track::TrackParCov::MatrixDSym5 cov5;
306318
float chi2Match = trCosmBtm.getPredictedChi2(trCosmTop, cov5);
319+
if (mMatchParams->maxChi2Match >= 0.f && chi2Match > mMatchParams->maxChi2Match) {
320+
LOG(debug) << "Top/Bottom refitted legs disagree, chi2Match " << chi2Match;
321+
continue;
322+
}
307323
if (!trCosmBtm.update(trCosmTop, cov5)) {
308324
LOG(debug) << "Top/Bottom update failed";
309325
continue;
310326
}
327+
// TPC-only legs on opposite sides: the legs' pT is required in checkPair, the refitted cosmic's here
328+
if (mSeeds[rec.id0].tpcSide * mSeeds[rec.id1].tpcSide < 0 && std::abs(trCosmBtm.getQ2Pt()) > mQ2PtCutoffOppositeSides) {
329+
LOG(debug) << "Cosmic with legs on opposite TPC sides below minPtOppositeSides";
330+
continue;
331+
}
311332
// create final track
312333
mCosmicTracks.emplace_back(mSeeds[poolEntryID[btm]].origID, mSeeds[poolEntryID[top]].origID, trCosmBtm, trCosmTop, chi2, chi2Match, nclTot, t0, dt);
313334
if (mUseMC) {
@@ -424,10 +445,18 @@ MatchCosmics::RejFlag MatchCosmics::checkPair(int i, int j)
424445
return (rej = RejTime); // since the brackets are sorted in tmin, all following tbj will also exceed tbi
425446
}
426447
float chi2 = 1.e9f;
448+
float tCommon = 0.f; // time fixed by z continuity of TPC-only legs on opposite sides, used by the refit
449+
float tCommonErr = -1.f; // its error (< 0: not fixed)
427450

428451
// check
429452
// 1) crude check on tgl and q/pt (if B!=0). Note: back-to-back tracks will have mutually params (see TrackPar::invertParam)
430453
while (1) {
454+
// TPC-only legs on opposite sides: their z continuity defines the time, so z does not reject random pairs of collision tracks; require
455+
// the pT of a cosmic for both legs already here, so that such a pair cannot win against the true partner of one of its legs
456+
if (seed0.tpcSide * seed1.tpcSide < 0 && std::max(std::abs(seed0.getQ2Pt()), std::abs(seed1.getQ2Pt())) > mQ2PtCutoffOppositeSides) {
457+
rej = RejQ2Pt;
458+
break;
459+
}
431460
auto dTgl = seed0.getTgl() + seed1.getTgl();
432461
if (dTgl * dTgl > (mMatchParams->systSigma2[o2::track::kTgl] + seed0.getSigmaTgl2() + seed1.getSigmaTgl2()) * mMatchParams->crudeNSigma2Cut[o2::track::kTgl]) {
433462
rej = RejTgl;
@@ -440,6 +469,27 @@ MatchCosmics::RejFlag MatchCosmics::checkPair(int i, int j)
440469
break;
441470
}
442471
}
472+
if (mMatchParams->vetoSameHalf) {
473+
// a cosmic has its two legs on opposite sides of its closest approach to the beam line: project the legs' reference points (before
474+
// the propagation to the DCA) on the transverse direction of seed0 at its DCA; pieces of one leg are on the same side. Transverse
475+
// only: the z of a TPC-only track refers to its own time0, so z differences between the legs are meaningless. Skipped for
476+
// reference points close to the DCA (e.g. ITS-containing tracks), where the sign is undefined.
477+
std::array<float, 3> pca{};
478+
seed0.getXYZGlo(pca);
479+
const float phi = seed0.getAlpha() + std::asin(seed0.getSnp());
480+
const float dir[2] = {std::cos(phi), std::sin(phi)};
481+
float proj0 = 0.f;
482+
float proj1 = 0.f;
483+
for (int k = 0; k < 2; k++) {
484+
proj0 += (seed0.xyzRef[k] - pca[k]) * dir[k];
485+
proj1 += (seed1.xyzRef[k] - pca[k]) * dir[k];
486+
}
487+
constexpr float MinDist = 20.f; // cm
488+
if (std::abs(proj0) > MinDist && std::abs(proj1) > MinDist && proj0 * proj1 > 0.f) {
489+
rej = RejSameHalf;
490+
break;
491+
}
492+
}
443493
o2::track::TrackParCov seed1Inv = seed1;
444494
seed1Inv.invert();
445495
for (int i = 0; i < o2::track::kNParams; i++) { // add systematic error
@@ -462,9 +512,47 @@ MatchCosmics::RejFlag MatchCosmics::checkPair(int i, int j)
462512
break;
463513
}
464514
bool ignoreZ = seed0.origID.getSource() == o2d::GlobalTrackID::TPC || seed1.origID.getSource() == o2d::GlobalTrackID::TPC;
465-
// RSTODO this is simplification: one should constraint the TPC-only track Z by the time of other candidate (at least their difference of both tracks are TPC only).
466-
// If the shift is large, eventually the tracks need to be refitted.
467-
if (!ignoreZ) { // cut on Z makes no sense for TPC only tracks
515+
if (ignoreZ && mMatchParams->constrainTPCOnlyZ) {
516+
// a TPC-only track with clusters on one side has z relative to its time0: z(t) = z + side * vD * (t - tRef); a CE-crossing or
517+
// non-TPC-only track has an absolute z (side 0). Bring both legs to a common time where possible and test z; for legs on opposite
518+
// sides, z continuity fixes the common time, which must lie in both time brackets.
519+
const int side0 = seed0.tpcSide;
520+
const int side1 = seed1.tpcSide;
521+
const float sigZ2 = (seed0.getSigmaZ2() + seed1Inv.getSigmaZ2()) * mMatchParams->crudeNSigma2Cut[o2::track::kZ];
522+
if (side0 == 0 || side1 == 0 || side0 == side1) {
523+
float dZ = seed0.getZ() - seed1Inv.getZ();
524+
float dZTimeTol = 0.f; // the time of a non-TPC absolute leg is only known within its bracket (tRef is the bracket centre)
525+
if (side0 != 0 && side1 != 0) { // same side: the z offset is fixed by the difference of the reference times
526+
dZ -= side0 * mTPCVDrift * (seed0.tRef - seed1.tRef);
527+
} else if (side1 != 0) { // seed0 absolute: move seed1 to the time of seed0
528+
dZ -= side1 * mTPCVDrift * (seed0.tRef - seed1.tRef);
529+
if (seed0.origID.getSource() != o2d::GlobalTrackID::TPC) {
530+
dZTimeTol = 0.5f * mTPCVDrift * seed0.tBracket.delta();
531+
}
532+
} else if (side0 != 0) { // seed1 absolute: move seed0 to the time of seed1
533+
dZ += side0 * mTPCVDrift * (seed1.tRef - seed0.tRef);
534+
if (seed1.origID.getSource() != o2d::GlobalTrackID::TPC) {
535+
dZTimeTol = 0.5f * mTPCVDrift * seed1.tBracket.delta();
536+
}
537+
}
538+
const float dZTol = std::sqrt(sigZ2) + dZTimeTol;
539+
if (dZ * dZ > dZTol * dZTol) {
540+
rej = RejZ;
541+
break;
542+
}
543+
} else { // opposite sides
544+
const float t = 0.5f * (side0 * (seed1Inv.getZ() - seed0.getZ()) / mTPCVDrift + seed0.tRef + seed1.tRef);
545+
const float tTol = std::sqrt(sigZ2) / (2.f * mTPCVDrift);
546+
if (t < std::max(seed0.tBracket.getMin(), seed1.tBracket.getMin()) - tTol || t > std::min(seed0.tBracket.getMax(), seed1.tBracket.getMax()) + tTol) {
547+
rej = RejZ;
548+
break;
549+
}
550+
tCommon = t;
551+
tCommonErr = std::sqrt(seed0.getSigmaZ2() + seed1Inv.getSigmaZ2()) / (2.f * mTPCVDrift);
552+
}
553+
}
554+
// the z of a TPC-only leg refers to its own time0: it is tested above at a common time with constrainTPCOnlyZ, otherwise ignored
555+
if (!ignoreZ) { // both legs have an absolute z
468556
auto dZ = seed0.getZ() - seed1Inv.getZ();
469557
if (dZ * dZ > (seed0.getSigmaZ2() + seed1Inv.getSigmaZ2()) * mMatchParams->crudeNSigma2Cut[o2::track::kZ]) {
470558
rej = RejZ;
@@ -484,8 +572,8 @@ MatchCosmics::RejFlag MatchCosmics::checkPair(int i, int j)
484572
break;
485573
}
486574
rej = Accept;
487-
registerMatch(i, j, chi2);
488-
registerMatch(j, i, chi2); // the reverse reference can be also done in a separate loop
575+
registerMatch(i, j, chi2, tCommon, tCommonErr);
576+
registerMatch(j, i, chi2, tCommon, tCommonErr); // the reverse reference can be also done in a separate loop
489577
LOG(debug) << "Chi2 = " << chi2 << " NMatches " << mRecords.size();
490578
break;
491579
}
@@ -497,7 +585,8 @@ MatchCosmics::RejFlag MatchCosmics::checkPair(int i, int j)
497585
if (seed1I.rotate(seed0.getAlpha()) && o2::base::Propagator::Instance()->PropagateToXBxByBz(seed1I, seed0.getX(), mMatchParams->maxSnp, mMatchParams->maxStep, mMatchParams->matCorr)) {
498586
int rejI = int(rej);
499587
(*mDBGOut) << "match"
500-
<< "tf=" << mTFCount << "seed0=" << seed0 << "seed1=" << seed1I << "chi2Match=" << chi2 << "rej=" << rejI << "\n";
588+
<< "tf=" << mTFCount << "seed0=" << seed0 << "seed1=" << seed1I << "chi2Match=" << chi2 << "rej=" << rejI
589+
<< "side0=" << int(seed0.tpcSide) << "side1=" << int(seed1.tpcSide) << "tCommon=" << tCommon << "tCommonErr=" << tCommonErr << "\n";
501590
}
502591
}
503592
#endif
@@ -506,11 +595,11 @@ MatchCosmics::RejFlag MatchCosmics::checkPair(int i, int j)
506595
}
507596

508597
//________________________________________________________
509-
void MatchCosmics::registerMatch(int i, int j, float chi2)
598+
void MatchCosmics::registerMatch(int i, int j, float chi2, float tCommon, float tCommonErr)
510599
{
511600
/// register track index j as a match for track index i
512601
int newRef = mRecords.size();
513-
auto& matchRec = mRecords.emplace_back(MatchRecord{i, j, chi2, MinusOne});
602+
auto& matchRec = mRecords.emplace_back(MatchRecord{i, j, chi2, MinusOne, tCommon, tCommonErr});
514603
auto* best = &mSeeds[i].matchID;
515604
while (*best > MinusOne) {
516605
auto& oldMatchRec = mRecords[*best];
@@ -540,7 +629,7 @@ void MatchCosmics::createSeeds(const o2::globaltracking::RecoContainer& data)
540629
return true;
541630
}
542631
if constexpr (isTPCTrack<decltype(_tr)>()) {
543-
if (!this->mMatchParams->allowTPCOnly) {
632+
if (!this->mMatchParams->allowTPCOnly || _tr.getNClusters() < this->mMatchParams->minSeedNClTPC) {
544633
return true;
545634
}
546635
// unconstrained TPC track, with t0 = TrackTPC.getTime0+0.5*(DeltaFwd-DeltaBwd) and terr = 0.5*(DeltaFwd+DeltaBwd) in TimeBins
@@ -554,9 +643,14 @@ void MatchCosmics::createSeeds(const o2::globaltracking::RecoContainer& data)
554643
}
555644
terr += this->mMatchParams->timeToleranceMUS;
556645
trackEntry[_origID] = mSeeds.size();
557-
mSeeds.emplace_back(TrackSeed{_tr, {t0 - terr, t0 + terr}, _origID, MinusOne});
646+
auto& seed = mSeeds.emplace_back(TrackSeed{_tr, {t0 - terr, t0 + terr}, _origID, MinusOne});
647+
seed.setPID(o2::track::PID::Muon, true); // muon mass and charge for the material corrections, whatever the leg's dE/dx PID
648+
seed.getXYZGlo(seed.xyzRef);
649+
seed.tRef = t0;
558650
if constexpr (isTPCTrack<decltype(_tr)>()) {
559-
mSeeds.back().setCov(this->mMatchParams->tpcExtraZError2 + _tr.getCov()[o2::track::kSigZ2], o2::track::kSigZ2);
651+
seed.setCov(this->mMatchParams->tpcExtraZError2 + _tr.getCov()[o2::track::kSigZ2], o2::track::kSigZ2);
652+
seed.tRef = _tr.getTime0() * this->mTPCTBinMUS; // the z of a TPC-only track refers to its time0
653+
seed.tpcSide = _tr.hasASideClustersOnly() ? 1 : (_tr.hasCSideClustersOnly() ? -1 : 0);
560654
}
561655
return true;
562656
} else {
@@ -603,10 +697,13 @@ void MatchCosmics::updateTimeDependentParams()
603697
mBz = o2::base::Propagator::Instance()->getNominalBz();
604698
mFieldON = std::abs(mBz) > 0.01;
605699
mQ2PtCutoff = 1.f / std::max(0.05f, mMatchParams->minSeedPt);
700+
mQ2PtCutoffOppositeSides = mMatchParams->minPtOppositeSides > 0.f ? 1.f / mMatchParams->minPtOppositeSides : 1e9;
606701
if (mFieldON) {
607702
mQ2PtCutoff *= 5.00668 / std::abs(mBz);
703+
mQ2PtCutoffOppositeSides *= 5.00668 / std::abs(mBz);
608704
} else {
609705
mQ2PtCutoff = 1e9;
706+
mQ2PtCutoffOppositeSides = 1e9;
610707
}
611708
}
612709

0 commit comments

Comments
 (0)