|
30 | 30 | #include "DetectorsCalibration/IntegratedClusterCalibrator.h" |
31 | 31 | #include "CommonUtils/TreeStreamRedirector.h" |
32 | 32 | #include "MathUtils/Tsallis.h" |
| 33 | +#include "MathUtils/Utils.h" |
33 | 34 | #include "ReconstructionDataFormats/TrackTPCITS.h" |
34 | 35 | #include "ReconstructionDataFormats/PrimaryVertex.h" |
35 | 36 | #include "ReconstructionDataFormats/VtxTrackIndex.h" |
@@ -71,7 +72,7 @@ class TPCTimeSeries : public Task |
71 | 72 | uint8_t trdPattern = 0; |
72 | 73 | uint8_t nTRDTracklets = 0; |
73 | 74 | int trackletIndices[6] = {-1, -1, -1, -1, -1, -1}; |
74 | | - o2::track::TrackParCov trdTrackParCov; // TRD track state for propagation to the common local X = 275 cm plane; filled only with --store-full-trackpar |
| 75 | + o2::track::TrackParCov trdTrackParCov; // TRD track state for propagation to the common local X = 275 cm plane |
75 | 76 | bool hasTRDTrackPar = false; |
76 | 77 | }; |
77 | 78 |
|
@@ -398,10 +399,8 @@ class TPCTimeSeries : public Task |
398 | 399 | trdData.trackletIndices[iLay] = trkltId; |
399 | 400 | } |
400 | 401 | } |
401 | | - if (mStoreFullTrackPar) { |
402 | | - trdData.trdTrackParCov = o2::track::TrackParCov(trdTrack); // TrackTRD base state, not validated as the outer/entrance state (open Phase 0.4 finding) |
403 | | - trdData.hasTRDTrackPar = true; |
404 | | - } |
| 402 | + trdData.trdTrackParCov = o2::track::TrackParCov(trdTrack); // TrackTRD base state, not validated as the outer/entrance state (open Phase 0.4 finding) |
| 403 | + trdData.hasTRDTrackPar = true; |
405 | 404 | tpcToTRDMap[refTPC] = trdData; |
406 | 405 | } |
407 | 406 | } |
@@ -1217,7 +1216,7 @@ class TPCTimeSeries : public Task |
1217 | 1216 | float mMaxdEdxRegionRatio{0.5}; ///< maximum abs dedx region ratio: log(dedx_region/dedx) |
1218 | 1217 | float mSamplingFactor{0.1}; ///< sampling factor in case sampling is used for unbinned data |
1219 | 1218 | bool mSampleTsallis{false}; ///< perform sampling of unbinned data |
1220 | | - bool mStoreFullTrackPar{false}; ///< experimental: compute and store tpcOut/trdIn/tpcAtVtx TrackPar and TPC-TRD chi2 (constant per job) |
| 1219 | + bool mStoreFullTrackPar{false}; ///< experimental: store tpcOut/trdIn/tpcAtVtx as TrackPar (constant per job) |
1221 | 1220 | uint8_t mTRDInReadout{255}; ///< TRD in detector readout (GRPECS): 1 yes, 0 no, 255 unknown |
1222 | 1221 | std::vector<std::mt19937> mGenerator; ///< random generator for debug tree sampling |
1223 | 1222 | std::vector<std::unique_ptr<o2::utils::TreeStreamRedirector>> mStreamer; ///< streamer for unbinned data |
@@ -1485,46 +1484,55 @@ class TPCTimeSeries : public Task |
1485 | 1484 | } |
1486 | 1485 | } |
1487 | 1486 |
|
1488 | | - // Optional TPC-out / TRD-in states on a common local X plane (experimental, --store-full-trackpar, default off). |
| 1487 | + // TPC-out / TRD-in states on a common local X plane, computed for every written entry (Architect decision 2026-10-28: |
| 1488 | + // residuals always stored; only the full TrackPar objects depend on --store-full-trackpar). |
1489 | 1489 | // Open Phase 0.4 findings, deferred: the target is local X = kTPCTRDMiddle in the frame rotated to the track |
1490 | 1490 | // position angle (lab radius = sqrt(X^2 + Y^2), not exactly 275 cm), and the TRD starting state is the TrackTRD |
1491 | | - // base state, not validated as the outer/entrance state. With the switch off nothing below is computed. |
1492 | | - static constexpr float kTPCTRDMiddle = 275.f; // cm, common local X plane between TPC outer wall and TRD layer 0 |
1493 | | - o2::track::TrackParCov tpcOutCov; // local temporary with covariance (needed for chi2); persisted as TrackPar |
| 1491 | + // base state (TrackTRD carries a single parameter set), not validated as the outer/entrance state. |
| 1492 | + static constexpr float kTPCTRDMiddle = 275.f; // cm, common local X plane between TPC outer wall and TRD layer 0 |
| 1493 | + static constexpr uint32_t kDeltaTRDTPCMask = 0xFFFFE000; // keep 10 mantissa bits: float16-like relative precision ~1e-3 |
| 1494 | + o2::track::TrackParCov tpcOutCov; // local temporary with covariance (needed for chi2); persisted as TrackPar |
1494 | 1495 | o2::track::TrackParCov trdInCov; |
1495 | | - uint8_t tpcOutOK = 255; // 0 propagated, 2 propagation failed, 255 switch off (not computed) |
1496 | | - uint8_t trdInOK = 255; // 0 propagated, 1 not attempted (no TRD match or tpcOutOK != 0), 2 propagation failed, 255 switch off; count TRD matches with trdPattern > 0 |
1497 | | - float chi2PhiTPCTRD = -1.f; // -1: not computed (switch off, trdInOK != 0) or singular covariance |
| 1496 | + uint8_t tpcOutOK = 2; // 0 propagated, 2 propagation failed |
| 1497 | + uint8_t trdInOK = 1; // 0 propagated, 1 not attempted (no TRD match or tpcOutOK != 0), 2 propagation failed; count TRD matches with trdPattern > 0 |
| 1498 | + float chi2PhiTPCTRD = -1.f; // -1: not computed (trdInOK != 0) or singular covariance |
1498 | 1499 | float chi2ZTPCTRD = -1.f; |
1499 | | - if (mStoreFullTrackPar) { |
1500 | | - // D1: TPC outer → kTPCTRDMiddle |
1501 | | - tpcOutCov = o2::track::TrackParCov(tracksTPC[iTrk].getParamOut()); |
1502 | | - tpcOutOK = 2; // default: propagation failed |
1503 | | - { |
1504 | | - // rotate to sector angle at current position |
1505 | | - float sn = std::sin(tpcOutCov.getAlpha()); |
1506 | | - float cs = std::cos(tpcOutCov.getAlpha()); |
1507 | | - float gy = tpcOutCov.getX() * sn + tpcOutCov.getY() * cs; |
1508 | | - float gx = tpcOutCov.getX() * cs - tpcOutCov.getY() * sn; |
1509 | | - if (tpcOutCov.rotate(std::atan2(gy, gx)) && |
1510 | | - propagator->propagateTo(tpcOutCov, kTPCTRDMiddle, false, mMaxSnp, mCoarseStep, mMatType)) { |
1511 | | - tpcOutOK = 0; |
1512 | | - } |
| 1500 | + // TRD - TPC residuals at the common plane (same alpha, same X), parameters 0..4 = Y, Z, Snp, Tgl, Q2Pt; -999 if trdInOK != 0 |
| 1501 | + float deltaP0TRDTPC = -999.f; |
| 1502 | + float deltaP1TRDTPC = -999.f; |
| 1503 | + float deltaP2TRDTPC = -999.f; |
| 1504 | + float deltaP3TRDTPC = -999.f; |
| 1505 | + float deltaP4TRDTPC = -999.f; |
| 1506 | + // D1: TPC outer → kTPCTRDMiddle |
| 1507 | + tpcOutCov = o2::track::TrackParCov(tracksTPC[iTrk].getParamOut()); |
| 1508 | + { |
| 1509 | + // rotate to sector angle at current position |
| 1510 | + float sn = std::sin(tpcOutCov.getAlpha()); |
| 1511 | + float cs = std::cos(tpcOutCov.getAlpha()); |
| 1512 | + float gy = tpcOutCov.getX() * sn + tpcOutCov.getY() * cs; |
| 1513 | + float gx = tpcOutCov.getX() * cs - tpcOutCov.getY() * sn; |
| 1514 | + if (tpcOutCov.rotate(std::atan2(gy, gx)) && |
| 1515 | + propagator->propagateTo(tpcOutCov, kTPCTRDMiddle, false, mMaxSnp, mCoarseStep, mMatType)) { |
| 1516 | + tpcOutOK = 0; |
1513 | 1517 | } |
| 1518 | + } |
1514 | 1519 |
|
1515 | | - // D2: TRD matched → kTPCTRDMiddle, rotated to SAME alpha as TPC out |
1516 | | - trdInOK = 1; // default: not attempted |
1517 | | - if (itTRD != tpcToTRDMap.end() && itTRD->second.hasTRDTrackPar && tpcOutOK == 0) { |
1518 | | - trdInCov = o2::track::TrackParCov(itTRD->second.trdTrackParCov); |
1519 | | - // rotate to TPC alpha FIRST, then propagate — guarantees same frame + same X |
1520 | | - if (trdInCov.rotate(tpcOutCov.getAlpha()) && |
1521 | | - propagator->propagateTo(trdInCov, kTPCTRDMiddle, false, mMaxSnp, mCoarseStep, mMatType)) { |
1522 | | - trdInOK = 0; |
1523 | | - chi2PhiTPCTRD = chi2Match_Phi(tpcOutCov, trdInCov); |
1524 | | - chi2ZTPCTRD = chi2Match_Z(tpcOutCov, trdInCov); |
1525 | | - } else { |
1526 | | - trdInOK = 2; // propagation failed |
1527 | | - } |
| 1520 | + // D2: TRD matched → kTPCTRDMiddle, rotated to SAME alpha as TPC out |
| 1521 | + if (itTRD != tpcToTRDMap.end() && itTRD->second.hasTRDTrackPar && tpcOutOK == 0) { |
| 1522 | + trdInCov = o2::track::TrackParCov(itTRD->second.trdTrackParCov); |
| 1523 | + // rotate to TPC alpha FIRST, then propagate — guarantees same frame + same X |
| 1524 | + if (trdInCov.rotate(tpcOutCov.getAlpha()) && |
| 1525 | + propagator->propagateTo(trdInCov, kTPCTRDMiddle, false, mMaxSnp, mCoarseStep, mMatType)) { |
| 1526 | + trdInOK = 0; |
| 1527 | + chi2PhiTPCTRD = chi2Match_Phi(tpcOutCov, trdInCov); |
| 1528 | + chi2ZTPCTRD = chi2Match_Z(tpcOutCov, trdInCov); |
| 1529 | + deltaP0TRDTPC = o2::math_utils::truncateFloatFraction(trdInCov.getParam(0) - tpcOutCov.getParam(0), kDeltaTRDTPCMask); |
| 1530 | + deltaP1TRDTPC = o2::math_utils::truncateFloatFraction(trdInCov.getParam(1) - tpcOutCov.getParam(1), kDeltaTRDTPCMask); |
| 1531 | + deltaP2TRDTPC = o2::math_utils::truncateFloatFraction(trdInCov.getParam(2) - tpcOutCov.getParam(2), kDeltaTRDTPCMask); |
| 1532 | + deltaP3TRDTPC = o2::math_utils::truncateFloatFraction(trdInCov.getParam(3) - tpcOutCov.getParam(3), kDeltaTRDTPCMask); |
| 1533 | + deltaP4TRDTPC = o2::math_utils::truncateFloatFraction(trdInCov.getParam(4) - tpcOutCov.getParam(4), kDeltaTRDTPCMask); |
| 1534 | + } else { |
| 1535 | + trdInOK = 2; // propagation failed |
1528 | 1536 | } |
1529 | 1537 | } |
1530 | 1538 |
|
@@ -1693,12 +1701,17 @@ class TPCTimeSeries : public Task |
1693 | 1701 | << "nTRDTracklets=" << nTRDTracklets |
1694 | 1702 | << "trdTracklets=" << trdTrackletVec |
1695 | 1703 | << "trdCalibTracklets=" << trdCalibVec |
1696 | | - // TPC out / TRD in on the common local X = 275 cm plane: status and matching chi2 |
1697 | | - // (255 / -1 when --store-full-trackpar is off; the TrackPar objects are written above) |
| 1704 | + // TPC out / TRD in on the common local X = 275 cm plane: status, matching chi2 and TRD - TPC residuals |
| 1705 | + // (the full TrackPar objects are written above, only with --store-full-trackpar) |
1698 | 1706 | << "tpcOutOK=" << tpcOutOK |
1699 | 1707 | << "trdInOK=" << trdInOK |
1700 | 1708 | << "chi2PhiTPCTRD=" << chi2PhiTPCTRD |
1701 | 1709 | << "chi2ZTPCTRD=" << chi2ZTPCTRD |
| 1710 | + << "deltaP0TRDTPC=" << deltaP0TRDTPC |
| 1711 | + << "deltaP1TRDTPC=" << deltaP1TRDTPC |
| 1712 | + << "deltaP2TRDTPC=" << deltaP2TRDTPC |
| 1713 | + << "deltaP3TRDTPC=" << deltaP3TRDTPC |
| 1714 | + << "deltaP4TRDTPC=" << deltaP4TRDTPC |
1702 | 1715 | // TRD in detector readout for this run (GRPECS): 1 yes, 0 no, 255 unknown |
1703 | 1716 | << "trdInReadout=" << mTRDInReadout |
1704 | 1717 | << "chi2match_ITSTPC=" << chi2match_ITSTPC |
@@ -2149,7 +2162,7 @@ o2::framework::DataProcessorSpec getTPCTimeSeriesSpec(const bool disableWriter, |
2149 | 2162 | {"sample-unbinned-tsallis", VariantType::Bool, false, {"Perform sampling of unbinned data based on Tsallis function"}}, |
2150 | 2163 | {"sampling-factor", VariantType::Float, 0.001f, {"Sampling factor in case sample-unbinned-tsallis is used"}}, |
2151 | 2164 | {"disable-min-bias-trigger", VariantType::Bool, false, {"Disable the minimum bias trigger for skimmed data"}}, |
2152 | | - {"store-full-trackpar", VariantType::Bool, false, {"Experimental: compute TPC-out/TRD-in states on the common local X = 275 cm plane and the TPC-TRD matching chi2, and store tpcOut, trdIn, tpcAtVtx as TrackPar in the unbinned tree"}}, |
| 2165 | + {"store-full-trackpar", VariantType::Bool, false, {"Experimental: store tpcOut, trdIn (common local X = 275 cm plane) and tpcAtVtx as TrackPar in the unbinned tree"}}, |
2153 | 2166 | {"out-file-unbinned", VariantType::String, "time_series_tracks.root", {"name of the output file for the unbinned data"}}, |
2154 | 2167 | {"max-occupancy-bins", VariantType::Int, 912, {"Maximum number of occupancy bins"}}}}; |
2155 | 2168 | } |
|
0 commit comments