Skip to content

Commit 8b9925a

Browse files
miranov25miranov25
authored andcommitted
TPC TimeSeries: Phase 0.4 — TrackParCov at R=275 + vertex + chi2Match
Store full TrackParCov (params + covariance) at three reference surfaces: tpcOut: TPC outer at kTPCTRDMiddle (275 cm), from getParamOut() trdIn: TRD matched at 275 cm, same alpha as TPC out tpcAtVtx: TPC track at vertex (propagated to DCA) itstpcAtVtx: ITS-TPC track at vertex (propagated to DCA) chi2Match_Phi: reusable 3x3 chi2 (Y, Snp, Q2Pt) — 3 DOF chi2Match_Z: reusable 2x2 chi2 (Z, Tgl) — 2 DOF Both stored per track: chi2PhiTPCTRD, chi2ZTPCTRD.
1 parent 04ab677 commit 8b9925a

1 file changed

Lines changed: 115 additions & 0 deletions

File tree

‎Detectors/TPC/workflow/src/TPCTimeSeriesSpec.cxx‎

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,61 @@ class TPCTimeSeries : public Task
7171
uint8_t trdPattern = 0;
7272
uint8_t nTRDTracklets = 0;
7373
int trackletIndices[6] = {-1, -1, -1, -1, -1, -1};
74+
o2::track::TrackParCov trdTrackParCov; // Phase 0.4: TRD track for propagation to R=275
75+
bool hasTRDTrackPar = false;
7476
};
7577

78+
/// Chi2 match in bending plane (Y, Snp, Q2Pt) — 3 DOF
79+
/// Both tracks must be at the same X and alpha.
80+
/// Returns -1 if covariance matrix is singular.
81+
static float chi2Match_Phi(const o2::track::TrackParCov& trk1, const o2::track::TrackParCov& trk2)
82+
{
83+
float d0 = trk1.getY() - trk2.getY();
84+
float d1 = trk1.getSnp() - trk2.getSnp();
85+
float d2 = trk1.getQ2Pt() - trk2.getQ2Pt();
86+
// Combined covariance C = C1 + C2
87+
float c00 = trk1.getSigmaY2() + trk2.getSigmaY2();
88+
float c01 = trk1.getSigmaSnpY() + trk2.getSigmaSnpY();
89+
float c02 = trk1.getSigma1PtY() + trk2.getSigma1PtY();
90+
float c11 = trk1.getSigmaSnp2() + trk2.getSigmaSnp2();
91+
float c12 = trk1.getSigma1PtSnp() + trk2.getSigma1PtSnp();
92+
float c22 = trk1.getSigma1Pt2() + trk2.getSigma1Pt2();
93+
float det = c00 * (c11 * c22 - c12 * c12)
94+
- c01 * (c01 * c22 - c12 * c02)
95+
+ c02 * (c01 * c12 - c11 * c02);
96+
if (std::abs(det) < 1e-30f) {
97+
return -1.f;
98+
}
99+
float detInv = 1.f / det;
100+
float i00 = (c11 * c22 - c12 * c12) * detInv;
101+
float i01 = (c02 * c12 - c01 * c22) * detInv;
102+
float i02 = (c01 * c12 - c02 * c11) * detInv;
103+
float i11 = (c00 * c22 - c02 * c02) * detInv;
104+
float i12 = (c01 * c02 - c00 * c12) * detInv;
105+
float i22 = (c00 * c11 - c01 * c01) * detInv;
106+
return d0 * (i00 * d0 + i01 * d1 + i02 * d2)
107+
+ d1 * (i01 * d0 + i11 * d1 + i12 * d2)
108+
+ d2 * (i02 * d0 + i12 * d1 + i22 * d2);
109+
}
110+
111+
/// Chi2 match in non-bending plane (Z, Tgl) — 2 DOF
112+
/// Both tracks must be at the same X and alpha.
113+
/// Returns -1 if covariance matrix is singular.
114+
static float chi2Match_Z(const o2::track::TrackParCov& trk1, const o2::track::TrackParCov& trk2)
115+
{
116+
float d0 = trk1.getZ() - trk2.getZ();
117+
float d1 = trk1.getTgl() - trk2.getTgl();
118+
float c00 = trk1.getSigmaZ2() + trk2.getSigmaZ2();
119+
float c01 = trk1.getSigmaTglZ() + trk2.getSigmaTglZ();
120+
float c11 = trk1.getSigmaTgl2() + trk2.getSigmaTgl2();
121+
float det = c00 * c11 - c01 * c01;
122+
if (std::abs(det) < 1e-30f) {
123+
return -1.f;
124+
}
125+
float detInv = 1.f / det;
126+
return (d0 * d0 * c11 - 2.f * d0 * d1 * c01 + d1 * d1 * c00) * detInv;
127+
}
128+
76129
/// \constructor
77130
TPCTimeSeries(std::shared_ptr<o2::base::GRPGeomRequest> req, const bool disableWriter, const o2::base::Propagator::MatCorrType matType, const bool enableUnbinnedWriter, const bool tpcOnly, std::shared_ptr<o2::globaltracking::DataRequest> dr) : mCCDBRequest(req), mDisableWriter(disableWriter), mMatType(matType), mUnbinnedWriter(enableUnbinnedWriter), mTPCOnly(tpcOnly), mDataRequest(dr) {};
78131

@@ -341,6 +394,8 @@ class TPCTimeSeries : public Task
341394
trdData.trackletIndices[iLay] = trkltId;
342395
}
343396
}
397+
trdData.trdTrackParCov = o2::track::TrackParCov(trdTrack);
398+
trdData.hasTRDTrackPar = true;
344399
tpcToTRDMap[refTPC] = trdData;
345400
}
346401
}
@@ -1421,6 +1476,55 @@ class TPCTimeSeries : public Task
14211476
}
14221477
}
14231478
}
1479+
1480+
// Phase 0.4: TPC out / TRD in at kTPCTRDMiddle, same frame, same X
1481+
static constexpr float kTPCTRDMiddle = 275.f; // cm, midpoint TPC outer / TRD layer 0
1482+
auto propagator = o2::base::Propagator::Instance();
1483+
1484+
// D1: TPC outer → kTPCTRDMiddle
1485+
o2::track::TrackParCov tpcOutCov(tracksTPC[iTrk].getParamOut());
1486+
uint8_t tpcOutOK = 2; // default: propagation failed
1487+
{
1488+
// rotate to sector angle at current position
1489+
float sn = std::sin(tpcOutCov.getAlpha());
1490+
float cs = std::cos(tpcOutCov.getAlpha());
1491+
float gy = tpcOutCov.getX() * sn + tpcOutCov.getY() * cs;
1492+
float gx = tpcOutCov.getX() * cs - tpcOutCov.getY() * sn;
1493+
if (tpcOutCov.rotate(std::atan2(gy, gx)) &&
1494+
propagator->propagateTo(tpcOutCov, kTPCTRDMiddle, false, mMaxSnp, mCoarseStep, mMatType)) {
1495+
tpcOutOK = 0;
1496+
}
1497+
}
1498+
1499+
// D2: TRD matched → kTPCTRDMiddle, rotated to SAME alpha as TPC out
1500+
o2::track::TrackParCov trdInCov;
1501+
uint8_t trdInOK = 1; // default: no TRD match
1502+
float chi2PhiTPCTRD = -1.f;
1503+
float chi2ZTPCTRD = -1.f;
1504+
if (itTRD != tpcToTRDMap.end() && itTRD->second.hasTRDTrackPar && tpcOutOK == 0) {
1505+
trdInCov = o2::track::TrackParCov(itTRD->second.trdTrackParCov);
1506+
// rotate to TPC alpha FIRST, then propagate — guarantees same frame + same X
1507+
if (trdInCov.rotate(tpcOutCov.getAlpha()) &&
1508+
propagator->propagateTo(trdInCov, kTPCTRDMiddle, false, mMaxSnp, mCoarseStep, mMatType)) {
1509+
trdInOK = 0;
1510+
chi2PhiTPCTRD = chi2Match_Phi(tpcOutCov, trdInCov);
1511+
chi2ZTPCTRD = chi2Match_Z(tpcOutCov, trdInCov);
1512+
} else {
1513+
trdInOK = 2; // propagation failed
1514+
}
1515+
}
1516+
1517+
// ITS-TPC track at vertex (full TrackParCov, propagated to DCA)
1518+
o2::track::TrackParCov itstpcAtVtx;
1519+
bool hasITSTPCAtVtx = false;
1520+
if (hasITSTPC) {
1521+
itstpcAtVtx = tracksITSTPC[idxITSTPC.front()];
1522+
o2::dataformats::DCA dcaTmp;
1523+
if (propagator->propagateToDCA(vertex.getXYZ(), itstpcAtVtx, propagator->getNominalBz(), mFineStep, mMatType, &dcaTmp)) {
1524+
hasITSTPCAtVtx = true;
1525+
}
1526+
}
1527+
14241528
int typeSide = 2; // A- and C-Side cluster
14251529
if (trackFull.hasASideClustersOnly()) {
14261530
typeSide = 0;
@@ -1563,6 +1667,17 @@ class TPCTimeSeries : public Task
15631667
<< "nTRDTracklets=" << nTRDTracklets
15641668
<< "trdTracklets=" << trdTrackletVec
15651669
<< "trdCalibTracklets=" << trdCalibVec
1670+
// Phase 0.4: TPC out / TRD in at R=275 cm
1671+
<< "tpcOut=" << tpcOutCov
1672+
<< "tpcOutOK=" << tpcOutOK
1673+
<< "trdIn=" << trdInCov
1674+
<< "trdInOK=" << trdInOK
1675+
<< "chi2PhiTPCTRD=" << chi2PhiTPCTRD
1676+
<< "chi2ZTPCTRD=" << chi2ZTPCTRD
1677+
// Track parameters at vertex (full TrackParCov)
1678+
<< "tpcAtVtx=" << track
1679+
<< "itstpcAtVtx=" << itstpcAtVtx
1680+
<< "hasITSTPCAtVtx=" << hasITSTPCAtVtx
15661681
<< "chi2match_ITSTPC=" << chi2match_ITSTPC
15671682
<< "PID=" << trkOrig.getPID().getID()
15681683
// TPC cov at vertex (without vertex constrained)

0 commit comments

Comments
 (0)