Skip to content

Commit 48a37e7

Browse files
miranov25claude
andcommitted
TPC TimeSeries: TRD read out in the collision, vertex contributor counts
- TRD-triggered BCs are collected once per TF from the TRD trigger records (bogus bc >= 3564 dropped). Per entry, trdTrigDBCBefore/After give the closest TRD trigger to the BC range [IRMin, IRMax] of the entry's vertex: both 0 if a trigger lies inside the range, else the distance in BC before the range start (< 0) and after its end (> 0); -999999/999999 if none or no vertex BC range. - vertex_nContributorsITS/ITSTPC/TRD: contributor counts of the same vertex, so the TRD-matched fraction of high-multiplicity collisions gives a second, independent TRD-readout estimator. - The TRD-out state is taken with recoData.getTrackParamOut(gid). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01YYeB7SW1TM7vU8qhVHiG61
1 parent ed835a2 commit 48a37e7

1 file changed

Lines changed: 78 additions & 3 deletions

File tree

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

Lines changed: 78 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@
4545
#include "DataFormatsTRD/TrackTRD.h"
4646
#include "DataFormatsTRD/Tracklet64.h"
4747
#include "DataFormatsTRD/CalibratedTracklet.h"
48+
#include "DataFormatsTRD/TriggerRecord.h"
49+
#include "CommonConstants/LHCConstants.h"
4850
#include "TROOT.h"
4951
#include "ReconstructionDataFormats/MatchInfoTOF.h"
5052
#include "DataFormatsTOF/Cluster.h"
@@ -376,6 +378,20 @@ class TPCTimeSeries : public Task
376378
std::unordered_map<unsigned int, TRDTrackletData> tpcToTRDMap;
377379
auto trdTracklets = (mTPCOnly || !recoData.inputsTRD) ? gsl::span<const o2::trd::Tracklet64>() : recoData.getTRDTracklets();
378380
auto trdCalibTracklets = (mTPCOnly || !recoData.inputsTRD) ? gsl::span<const o2::trd::CalibratedTracklet>() : recoData.getTRDCalibratedTracklets();
381+
382+
// TRD-triggered BCs of this TF: TRD is read out only at these BCs. Built once per TF; per entry only the triggers closest
383+
// to the collision are stored (trdTrigDBCBefore/After). Records with bc >= LHCMaxBunches are dropped, as in the AOD producer.
384+
mTRDTrigBCs.clear();
385+
if (mUnbinnedWriter && !mTPCOnly && recoData.inputsTRD) {
386+
const auto trdTrig = recoData.getTRDTriggerRecords();
387+
mTRDTrigBCs.reserve(trdTrig.size());
388+
for (const auto& trg : trdTrig) {
389+
if (trg.getBCData().bc < o2::constants::lhc::LHCMaxBunches) {
390+
mTRDTrigBCs.push_back(trg.getBCData());
391+
}
392+
}
393+
std::sort(mTRDTrigBCs.begin(), mTRDTrigBCs.end());
394+
}
379395
if (mUnbinnedWriter && !mTPCOnly) {
380396
// scan ITS-TPC-TRD tracks
381397
auto itstpctrdTracks = recoData.getITSTPCTRDTracks<o2::trd::TrackTRD>();
@@ -399,9 +415,9 @@ class TPCTimeSeries : public Task
399415
trdData.trackletIndices[iLay] = trkltId;
400416
}
401417
}
402-
// outer state of the ITS-TPC-TRD track: outward refit through ITS, TPC and TRD, at the outermost TRD layer (as in
403-
// RecoContainer::getTrackParamOut). The base state of TrackTRD is the inward refit, which ends at the innermost ITS cluster.
404-
trdData.trdTrackParCov = trdTrack.getOuterParam();
418+
// TRD-out: outer state of the ITS-TPC-TRD track (outward refit through ITS, TPC and TRD, at the outermost TRD layer).
419+
// The base state of TrackTRD is the inward refit, which ends at the innermost ITS cluster.
420+
trdData.trdTrackParCov = recoData.getTrackParamOut(gid);
405421
trdData.hasTRDTrackPar = true;
406422
tpcToTRDMap[refTPC] = trdData;
407423
}
@@ -1220,6 +1236,10 @@ class TPCTimeSeries : public Task
12201236
bool mSampleTsallis{false}; ///< perform sampling of unbinned data
12211237
bool mStoreFullTrackPar{false}; ///< experimental: store tpcOut/trdIn/tpcAtVtx as TrackPar (constant per job)
12221238
uint8_t mTRDInReadout{255}; ///< TRD in detector readout (GRPECS): 1 yes, 0 no, 255 unknown
1239+
std::vector<o2::InteractionRecord> mTRDTrigBCs; ///< TRD-triggered BCs of the current TF, sorted
1240+
std::vector<int> mNContributorsITS; ///< per vertex ID: ITS-only PV contributors (current TF)
1241+
std::vector<int> mNContributorsITSTPC; ///< per vertex ID: ITS-TPC PV contributors, TRD/TOF-matched included (current TF)
1242+
std::vector<int> mNContributorsTRD; ///< per vertex ID: ITS-TPC-TRD (and -TOF) PV contributors (current TF)
12231243
std::vector<std::mt19937> mGenerator; ///< random generator for debug tree sampling
12241244
std::vector<std::unique_ptr<o2::utils::TreeStreamRedirector>> mStreamer; ///< streamer for unbinned data
12251245
float mXOuterMatching{60}; ///< reference x where delta track parameters for TPC with ITS-TPC track are stored in skimmed data
@@ -1310,6 +1330,11 @@ class TPCTimeSeries : public Task
13101330

13111331
// get vertex (check if vertex ID is valid). In case no vertex is assigned return nearest vertex or else default vertex
13121332
const auto vertex = (idxITSTPC.back() != -1) ? vertices[idxITSTPC.back()] : ((mNearestVtxTPC[iTrk] != -1) ? vertices[mNearestVtxTPC[iTrk]] : o2::dataformats::PrimaryVertex{});
1333+
// index of that vertex (-1: none) and its contributor counts, -1 without vertex
1334+
const int vtxID = (idxITSTPC.back() != -1) ? idxITSTPC.back() : mNearestVtxTPC[iTrk];
1335+
const int nContribITS = (vtxID >= 0 && vtxID < static_cast<int>(mNContributorsITS.size())) ? mNContributorsITS[vtxID] : -1;
1336+
const int nContribITSTPC = (vtxID >= 0 && vtxID < static_cast<int>(mNContributorsITSTPC.size())) ? mNContributorsITSTPC[vtxID] : -1;
1337+
const int nContribTRD = (vtxID >= 0 && vtxID < static_cast<int>(mNContributorsTRD.size())) ? mNContributorsTRD[vtxID] : -1;
13131338

13141339
// calculate DCAz: (time TPC track - time vertex) * vDrift + sign_side * vertexZ
13151340
const float signSide = trackFull.hasCSideClustersOnly() ? -1 : 1; // invert sign for C-side
@@ -1537,6 +1562,29 @@ class TPCTimeSeries : public Task
15371562
}
15381563
}
15391564

1565+
// TRD read out in the collision of this entry: TRD-triggered BCs closest to the BC range [IRMin, IRMax] of the entry's
1566+
// vertex. Both 0: a TRD trigger inside the range. Otherwise trdTrigDBCBefore < 0 = BCs from the range start back to the
1567+
// closest earlier trigger, trdTrigDBCAfter > 0 = BCs from the range end to the closest later trigger. Sentinels -999999 /
1568+
// 999999: no vertex with a BC range, or no such trigger in this TF.
1569+
int trdTrigDBCBefore = -999999;
1570+
int trdTrigDBCAfter = 999999;
1571+
if (vtxID >= 0 && !vertex.getIRMin().isDummy() && !vertex.getIRMax().isDummy()) {
1572+
const auto& irMin = vertex.getIRMin();
1573+
const auto& irMax = vertex.getIRMax();
1574+
const auto itTrig = std::lower_bound(mTRDTrigBCs.begin(), mTRDTrigBCs.end(), irMin); // first trigger at or after irMin
1575+
if (itTrig != mTRDTrigBCs.end() && *itTrig <= irMax) {
1576+
trdTrigDBCBefore = 0;
1577+
trdTrigDBCAfter = 0;
1578+
} else {
1579+
if (itTrig != mTRDTrigBCs.end()) {
1580+
trdTrigDBCAfter = static_cast<int>(itTrig->differenceInBC(irMax));
1581+
}
1582+
if (itTrig != mTRDTrigBCs.begin()) {
1583+
trdTrigDBCBefore = static_cast<int>((itTrig - 1)->differenceInBC(irMin));
1584+
}
1585+
}
1586+
}
1587+
15401588
int typeSide = 2; // A- and C-Side cluster
15411589
if (trackFull.hasASideClustersOnly()) {
15421590
typeSide = 0;
@@ -1676,6 +1724,12 @@ class TPCTimeSeries : public Task
16761724
<< "vertex_z=" << vertex.getZ()
16771725
<< "vertex_time=" << vertex.getTimeStamp().getTimeStamp()
16781726
<< "vertex_nContributors=" << vertex.getNContributors()
1727+
// contributor counts of the same vertex (-1 without vertex) and TRD triggers closest to its BC range
1728+
<< "vertex_nContributorsITS=" << nContribITS
1729+
<< "vertex_nContributorsITSTPC=" << nContribITSTPC
1730+
<< "vertex_nContributorsTRD=" << nContribTRD
1731+
<< "trdTrigDBCBefore=" << trdTrigDBCBefore
1732+
<< "trdTrigDBCAfter=" << trdTrigDBCAfter
16791733
<< "isNearestVertex=" << isNearestVtx
16801734
// tpc track properties
16811735
<< "pt=" << trkOrig.getPt()
@@ -1937,6 +1991,27 @@ class TPCTimeSeries : public Task
19371991
}
19381992
}
19391993

1994+
// per-vertex contributor counts, also written per entry of the unbinned tree (vertex_nContributorsITS/ITSTPC/TRD)
1995+
mNContributorsITS.assign(vertices.size(), 0);
1996+
mNContributorsITSTPC.assign(vertices.size(), 0);
1997+
mNContributorsTRD.assign(vertices.size(), 0);
1998+
const int nVertices = vertices.size();
1999+
for (const auto& [vID, n] : nContributors_ITS) {
2000+
if (vID >= 0 && vID < nVertices) {
2001+
mNContributorsITS[vID] = n;
2002+
}
2003+
}
2004+
for (const auto& [vID, n] : nContributors_ITSTPC) {
2005+
if (vID >= 0 && vID < nVertices) {
2006+
mNContributorsITSTPC[vID] = n;
2007+
}
2008+
}
2009+
for (const auto& [vID, n] : nContributors_TRD) {
2010+
if (vID >= 0 && vID < nVertices) {
2011+
mNContributorsTRD[vID] = n;
2012+
}
2013+
}
2014+
19402015
// calculate statistics
19412016
std::array<RobustAverage, 4> avgVtxITS;
19422017
std::array<RobustAverage, 4> avgVtxITSTPC;

0 commit comments

Comments
 (0)