Project
Loading...
Searching...
No Matches
TPCTimeSeriesSpec.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16
17#include "Framework/Task.h"
18#include "Framework/Logger.h"
24#include "TPCBase/Mapper.h"
32#include "MathUtils/Tsallis.h"
40#include <random>
41#include <chrono>
47#include "TROOT.h"
54
55using namespace o2::globaltracking;
59using namespace o2::framework;
60
61namespace o2
62{
63namespace tpc
64{
65
66class TPCTimeSeries : public Task
67{
68 public:
71 uint8_t trdPattern = 0;
72 uint8_t nTRDTracklets = 0;
73 int trackletIndices[6] = {-1, -1, -1, -1, -1, -1};
74 };
75
77 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) {};
78
80 {
82 mNMaxTracks = ic.options().get<int>("max-tracks");
83 mMinMom = ic.options().get<float>("min-momentum");
84 mMinNCl = ic.options().get<int>("min-cluster");
85 mMaxTgl = ic.options().get<float>("max-tgl");
86 mMaxQPt = ic.options().get<float>("max-qPt");
87 mCoarseStep = ic.options().get<float>("coarse-step");
88 mFineStep = ic.options().get<float>("fine-step");
89 mCutDCA = ic.options().get<float>("cut-DCA-median");
90 mCutRMS = ic.options().get<float>("cut-DCA-RMS");
91 mRefXSec = ic.options().get<float>("refX-for-sector");
92 mTglBins = ic.options().get<int>("tgl-bins");
93 mPhiBins = ic.options().get<int>("phi-bins");
94 mQPtBins = ic.options().get<int>("qPt-bins");
95 mNThreads = ic.options().get<int>("threads");
96 maxITSTPCDCAr = ic.options().get<float>("max-ITS-TPC-DCAr");
97 maxITSTPCDCAz = ic.options().get<float>("max-ITS-TPC-DCAz");
98 maxITSTPCDCAr_comb = ic.options().get<float>("max-ITS-TPC-DCAr_comb");
99 maxITSTPCDCAz_comb = ic.options().get<float>("max-ITS-TPC-DCAz_comb");
100 mTimeWindowMUS = ic.options().get<float>("time-window-mult-mus");
101 mMIPdEdx = ic.options().get<float>("MIP-dedx");
102 mMaxSnp = ic.options().get<float>("max-snp");
103 mXCoarse = ic.options().get<float>("mX-coarse");
104 mSqrt = ic.options().get<float>("sqrts");
105 mMultBins = ic.options().get<int>("mult-bins");
106 mMultMax = ic.options().get<int>("mult-max");
107 mMinTracksPerVertex = ic.options().get<int>("min-tracks-per-vertex");
108 mMaxdEdxRatio = ic.options().get<float>("max-dedx-ratio");
109 mMaxdEdxRegionRatio = ic.options().get<float>("max-dedx-region-ratio");
110 mSamplingFactor = ic.options().get<float>("sampling-factor");
111 mSampleTsallis = ic.options().get<bool>("sample-unbinned-tsallis");
112 mXOuterMatching = ic.options().get<float>("refX-for-outer-ITS");
113 mUseMinBiasTrigger = !ic.options().get<bool>("disable-min-bias-trigger");
114 mMaxOccupancyHistBins = ic.options().get<int>("max-occupancy-bins");
115
116 if (mUnbinnedWriter) {
117 for (int iThread = 0; iThread < mNThreads; ++iThread) {
118 mGenerator.emplace_back(std::mt19937(std::random_device{}()));
119 }
120 }
121 mBufferVals.resize(mNThreads);
122 mBufferDCA.setBinning(mPhiBins, mTglBins, mQPtBins, mMultBins, mMaxTgl, mMaxQPt, mMultMax);
123 if (mUnbinnedWriter) {
124 std::string outfile = ic.options().get<std::string>("out-file-unbinned");
125 if (mNThreads > 1) {
126 ROOT::EnableThreadSafety();
127 }
128 mStreamer.resize(mNThreads);
129 for (int iThread = 0; iThread < mNThreads; ++iThread) {
130 std::string outfileThr = outfile;
131 outfileThr.replace(outfileThr.length() - 5, outfileThr.length(), fmt::format("_{}.root", iThread));
132 LOGP(info, "Writing unbinned data to: {}", outfileThr);
133 mStreamer[iThread] = std::make_unique<o2::utils::TreeStreamRedirector>(outfileThr.data(), "recreate");
134 }
135 }
136 }
137
138 void run(ProcessingContext& pc) final
139 {
141 mTPCVDriftHelper.extractCCDBInputs(pc);
142 mPTHelper.extractCCDBInputs(pc);
143 if (mTPCVDriftHelper.isUpdated()) {
144 mTPCVDriftHelper.acknowledgeUpdate();
145 mVDrift = mTPCVDriftHelper.getVDriftObject().getVDrift();
146 LOGP(info, "Updated reference drift velocity to: {}", mVDrift);
147 }
148 pc.inputs().get<TTree*>("tpcSecFlucInfo");
149 mBufferDCA.mVDrift = mVDrift;
150
151 const int nBins = getNBins();
152
155 mBufferDCA.mSecEdgeFlucCorr = mSecEdgeFlucInfo.getSectorsAtTime(mRun, static_cast<long>(mTimeMS));
156 mBufferDCA.mTemperature = mPTHelper.getMeanTemperature(mTimeMS);
157 mBufferDCA.mPressure = mPTHelper.getPressure(mTimeMS);
158
159 // init only once
160 if (mAvgADCAr.size() != nBins) {
161 mBufferDCA.resize(nBins);
162 mAvgADCAr.resize(nBins);
163 mAvgCDCAr.resize(nBins);
164 mAvgADCAz.resize(nBins);
165 mAvgCDCAz.resize(nBins);
166 mAvgMeffA.resize(nBins);
167 mAvgMeffC.resize(nBins);
168 mAvgChi2MatchA.resize(nBins);
169 mAvgChi2MatchC.resize(nBins);
170 mMIPdEdxRatioQMaxA.resize(nBins);
171 mMIPdEdxRatioQMaxC.resize(nBins);
172 mMIPdEdxRatioQTotA.resize(nBins);
173 mMIPdEdxRatioQTotC.resize(nBins);
174 mTPCChi2A.resize(nBins);
175 mTPCChi2C.resize(nBins);
176 mTPCNClA.resize(nBins);
177 mTPCNClC.resize(nBins);
178 mLogdEdxQTotA.resize(nBins);
179 mLogdEdxQTotC.resize(nBins);
180 mLogdEdxQMaxA.resize(nBins);
181 mLogdEdxQMaxC.resize(nBins);
182 mITSPropertiesA.resize(nBins);
183 mITSPropertiesC.resize(nBins);
184 mITSTPCDeltaPA.resize(nBins);
185 mITSTPCDeltaPC.resize(nBins);
186 mSigmaYZA.resize(nBins);
187 mSigmaYZC.resize(nBins);
188 }
189
190 RecoContainer recoData;
191 recoData.collectData(pc, *mDataRequest.get());
192
193 // getting tracks
194 auto tracksTPC = recoData.getTPCTracks();
195 auto tracksITSTPC = mTPCOnly ? gsl::span<o2::dataformats::TrackTPCITS>() : recoData.getTPCITSTracks();
196 auto tracksITS = mTPCOnly ? gsl::span<o2::its::TrackITS>() : recoData.getITSTracks();
197
198 // getting the vertices
199 auto vertices = mTPCOnly ? gsl::span<o2::dataformats::PrimaryVertex>() : recoData.getPrimaryVertices();
200 auto primMatchedTracks = mTPCOnly ? gsl::span<o2::dataformats::VtxTrackIndex>() : recoData.getPrimaryVertexMatchedTracks(); // Global ID's for associated tracks
201 auto primMatchedTracksRef = mTPCOnly ? gsl::span<o2::dataformats::VtxTrackRef>() : recoData.getPrimaryVertexMatchedTrackRefs(); // references from vertex to these track IDs
202
203 // get occupancy map
204 mBufferDCA.mOccupancyMapTPC = std::vector<unsigned int>(recoData.occupancyMapTPC.begin(), recoData.occupancyMapTPC.end());
205 if (mBufferDCA.mOccupancyMapTPC.size() > mMaxOccupancyHistBins) {
206 mBufferDCA.mOccupancyMapTPC.resize(mMaxOccupancyHistBins);
207 }
208
209 // TOF clusters
210 const auto& tofClusters = mTPCOnly ? gsl::span<o2::tof::Cluster>() : recoData.getTOFClusters();
211
212 LOGP(info, "Processing {} vertices, {} primary matched vertices, {} TPC tracks, {} ITS tracks, {} ITS-TPC tracks, {} TOF clusters", vertices.size(), primMatchedTracks.size(), tracksTPC.size(), tracksITS.size(), tracksITSTPC.size(), tofClusters.size());
213
214 // calculate mean vertex, RMS and count vertices
215 auto indicesITSTPC_vtx = processVertices(vertices, primMatchedTracks, primMatchedTracksRef, recoData);
216
217 // storing indices to ITS-TPC tracks and vertex ID for tpc track
218 std::unordered_map<unsigned int, std::array<int, 2>> indicesITSTPC; // TPC track index -> ITS-TPC track index, vertex ID
219 // loop over all ITS-TPC tracks
220 for (int i = 0; i < tracksITSTPC.size(); ++i) {
221 auto it = indicesITSTPC_vtx.find(i);
222 // check if ITS-TPC track has attached vertex
223 const auto idxVtx = (it != indicesITSTPC_vtx.end()) ? (it->second) : -1;
224 // store TPC index and ITS-TPC+vertex index
225 indicesITSTPC[tracksITSTPC[i].getRefTPC().getIndex()] = {i, idxVtx};
226 }
227
228 std::vector<std::tuple<int, float, float, o2::track::TrackLTIntegral, double, float, unsigned int, unsigned short>> idxTPCTrackToTOFCluster; // store for each tpc track index the index to the TOF cluster
229
230 // get matches to TOF in case skimmed data is produced
231 if (mUnbinnedWriter) {
232 // getLTIntegralOut(), ///< L,TOF integral calculated during the propagation
233 // getSignal() mSignal = 0.0; ///< TOF time in ps
235 idxTPCTrackToTOFCluster = std::vector<std::tuple<int, float, float, o2::track::TrackLTIntegral, double, float, unsigned int, unsigned short>>(tracksTPC.size(), {-1, -999, -999, defLT, 0, 0, 0, 0});
236 const std::vector<gsl::span<const o2::dataformats::MatchInfoTOF>> tofMatches{recoData.getTPCTOFMatches(), recoData.getTPCTRDTOFMatches(), recoData.getITSTPCTOFMatches(), recoData.getITSTPCTRDTOFMatches()};
237
238 const auto& ft0rec = recoData.getFT0RecPoints();
239 // fill available FT0-AC event times vs BClong
240 std::map<ULong64_t, short> t0array;
241 for (const auto& t0 : ft0rec) {
242 if (!(t0.isValidTime(1) && t0.isValidTime(2))) { // skip if !(A & C)
243 continue;
244 }
245
246 auto bclong = t0.mIntRecord.differenceInBC(recoData.startIR);
247 if (t0array.find(bclong) == t0array.end()) { // add if it doesn't exist
248 t0array.emplace(std::make_pair(bclong, t0.getCollisionTime(0)));
249 }
250 }
251
252 static const double BC_TIME_INPS_INV = 1E-3 / o2::constants::lhc::LHCBunchSpacingNS;
253
254 // loop over ITS-TPC-TRD-TOF and ITS-TPC-TOF tracks an store for each ITS-TPC track the TOF track index
255 for (const auto& tofMatch : tofMatches) {
256 for (const auto& tpctofmatch : tofMatch) {
257 auto refTPC = recoData.getTPCContributorGID(tpctofmatch.getTrackRef());
258 if (refTPC.isIndexSet()) {
259 o2::track::TrackLTIntegral ltIntegral = tpctofmatch.getLTIntegralOut();
260 ULong64_t bclongtof = (tpctofmatch.getSignal() - 10000) * BC_TIME_INPS_INV;
261 double t0 = 0; // bclongtof * o2::constants::lhc::LHCBunchSpacingNS * 1E3; // if you want to subtract also the BC uncomment this part (-> tofsignal can be a float)
262 unsigned int mask = 0;
263 if (!(t0array.find(bclongtof) == t0array.end())) { // subtract FT0-AC if it exists in the same BC
264 t0 += t0array.find(bclongtof)->second;
265 mask |= o2::dataformats::MatchInfoTOF::QualityFlags::hasT0sameBC; // 8th bit if FT0-AC in same BC
266 }
267
268 double signal = tpctofmatch.getSignal() - t0;
269 float deltaT = tpctofmatch.getDeltaT();
270
271 float dy = tpctofmatch.getDYatTOF(); // residual orthogonal to the strip (it should be close to zero)
272 bool isMultiHitZ = tpctofmatch.getHitPatternUpDown();
273 bool isMultiHitX = tpctofmatch.getHitPatternLeftRight();
274 bool isMultiStripMatch = tpctofmatch.getChi2() < 1E-9;
275 float chi2 = tpctofmatch.getChi2();
276 bool hasT0_1BCbefore = (t0array.find(bclongtof - 1) != t0array.end());
277 bool hasT0_2BCbefore = (t0array.find(bclongtof - 2) != t0array.end());
278
279 if (isMultiHitX) { // 1nd bit on if multiple hits along X
281 }
282 if (isMultiHitZ) { // 2nd bit on if multiple hits along Z
284 }
285 if (fabs(dy) > 0.5) { // 3rd bit on if Y-residual too large
287 }
288 if (isMultiStripMatch) { // 4th bit on if two strips fired
290 }
291 if (chi2 > 1E-4) { // 5th bit on if chi2 > 1E-4 -> not inside the pad
293 }
294 if (chi2 > 3) { // 6th bit on if chi2 > 3
296 }
297 if (chi2 > 5) { // 7th bit on if chi2 > 5
299 }
300 if (hasT0_1BCbefore) { // 9th bit if FT0-AC also BC before
302 }
303 if (hasT0_2BCbefore) { // 10th bit if FT0-AC also 2BCs before
305 }
306
307 idxTPCTrackToTOFCluster[refTPC] = {tpctofmatch.getIdxTOFCl(), tpctofmatch.getDXatTOF(), tpctofmatch.getDZatTOF(), ltIntegral, signal, deltaT, mask, tpctofmatch.getChannel() % 8736};
308 }
309 }
310 }
311 }
312
313 // find nearest vertex of tracks which have no vertex assigned
314 findNearesVertex(tracksTPC, vertices);
315
316 // D2: build TPC track index → TRD tracklet data map (for unbinned output)
317 // For each TPC track that has a TRD match, store the TrackTRD tracklet indices
318 std::unordered_map<unsigned int, TRDTrackletData> tpcToTRDMap;
319 auto trdTracklets = (mTPCOnly || !recoData.inputsTRD) ? gsl::span<const o2::trd::Tracklet64>() : recoData.getTRDTracklets();
320 auto trdCalibTracklets = (mTPCOnly || !recoData.inputsTRD) ? gsl::span<const o2::trd::CalibratedTracklet>() : recoData.getTRDCalibratedTracklets();
321 if (mUnbinnedWriter && !mTPCOnly) {
322 // scan ITS-TPC-TRD tracks
323 auto itstpctrdTracks = recoData.getITSTPCTRDTracks<o2::trd::TrackTRD>();
324 for (unsigned int ig = 0; ig < itstpctrdTracks.size(); ++ig) {
325 auto gid = GTrackID(ig, GTrackID::ITSTPCTRD);
326 auto refTPC = recoData.getTPCContributorGID(gid);
327 if (!refTPC.isIndexSet()) {
328 continue;
329 }
330 auto refTRD = recoData.getSingleDetectorRefs(gid)[GTrackID::TRD];
331 if (!refTRD.isIndexSet()) {
332 continue;
333 }
334 const auto& trdTrack = recoData.getTrack<o2::trd::TrackTRD>(refTRD);
335 TRDTrackletData trdData;
336 for (int iLay = 0; iLay < 6; ++iLay) {
337 auto trkltId = trdTrack.getTrackletIndex(iLay);
338 if (trkltId >= 0) {
339 trdData.trdPattern |= (1 << iLay);
340 trdData.nTRDTracklets++;
341 trdData.trackletIndices[iLay] = trkltId;
342 }
343 }
344 tpcToTRDMap[refTPC] = trdData;
345 }
346 }
347
348 // getting cluster references for cluster bitmask
349 if (mUnbinnedWriter) {
350 mTPCTrackClIdx = pc.inputs().get<gsl::span<o2::tpc::TPCClRefElem>>("trackTPCClRefs");
351 mFirstTFOrbit = processing_helpers::getFirstTForbit(pc);
352 }
353
354 // get local multiplicity - count neighbouring tracks
355 findNNeighbourTracks(tracksTPC);
356
357 // reset buffers
358 for (int i = 0; i < nBins; ++i) {
359 for (int type = 0; type < mAvgADCAr[i].size(); ++type) {
360 mAvgADCAr[i][type].clear();
361 mAvgCDCAr[i][type].clear();
362 mAvgADCAz[i][type].clear();
363 mAvgCDCAz[i][type].clear();
364 }
365 for (int type = 0; type < mMIPdEdxRatioQMaxA[i].size(); ++type) {
366 mMIPdEdxRatioQMaxA[i][type].clear();
367 mMIPdEdxRatioQMaxC[i][type].clear();
368 mMIPdEdxRatioQTotA[i][type].clear();
369 mMIPdEdxRatioQTotC[i][type].clear();
370 mTPCChi2A[i][type].clear();
371 mTPCChi2C[i][type].clear();
372 mTPCNClA[i][type].clear();
373 mTPCNClC[i][type].clear();
374 mMIPdEdxRatioQMaxA[i][type].setUseWeights(false);
375 mMIPdEdxRatioQMaxC[i][type].setUseWeights(false);
376 mMIPdEdxRatioQTotA[i][type].setUseWeights(false);
377 mMIPdEdxRatioQTotC[i][type].setUseWeights(false);
378 mTPCChi2A[i][type].setUseWeights(false);
379 mTPCChi2C[i][type].setUseWeights(false);
380 mTPCNClA[i][type].setUseWeights(false);
381 mTPCNClC[i][type].setUseWeights(false);
382 }
383 for (int type = 0; type < mLogdEdxQTotA[i].size(); ++type) {
384 mLogdEdxQTotA[i][type].clear();
385 mLogdEdxQTotC[i][type].clear();
386 mLogdEdxQMaxA[i][type].clear();
387 mLogdEdxQMaxC[i][type].clear();
388 mLogdEdxQTotA[i][type].setUseWeights(false);
389 mLogdEdxQTotC[i][type].setUseWeights(false);
390 mLogdEdxQMaxA[i][type].setUseWeights(false);
391 mLogdEdxQMaxC[i][type].setUseWeights(false);
392 }
393 for (int j = 0; j < mITSPropertiesA[i].size(); ++j) {
394 mITSPropertiesA[i][j].clear();
395 mITSPropertiesC[i][j].clear();
396 mITSPropertiesA[i][j].setUseWeights(false);
397 mITSPropertiesC[i][j].setUseWeights(false);
398 }
399
400 for (int j = 0; j < mITSTPCDeltaPA[i].size(); ++j) {
401 mITSTPCDeltaPA[i][j].clear();
402 mITSTPCDeltaPC[i][j].clear();
403 mITSTPCDeltaPA[i][j].setUseWeights(false);
404 mITSTPCDeltaPC[i][j].setUseWeights(false);
405 }
406
407 for (int j = 0; j < mSigmaYZA[i].size(); ++j) {
408 mSigmaYZA[i][j].clear();
409 mSigmaYZC[i][j].clear();
410 mSigmaYZA[i][j].setUseWeights(false);
411 mSigmaYZC[i][j].setUseWeights(false);
412 }
413
414 for (int j = 0; j < mAvgMeffA[i].size(); ++j) {
415 mAvgMeffA[i][j].clear();
416 mAvgMeffC[i][j].clear();
417 mAvgChi2MatchA[i][j].clear();
418 mAvgChi2MatchC[i][j].clear();
419 mAvgMeffA[i][j].setUseWeights(false);
420 mAvgMeffC[i][j].setUseWeights(false);
421 mAvgChi2MatchA[i][j].setUseWeights(false);
422 mAvgChi2MatchC[i][j].setUseWeights(false);
423 }
424 }
425
426 for (int i = 0; i < mNThreads; ++i) {
427 mBufferVals[i].front().clear();
428 mBufferVals[i].back().clear();
429 }
430
431 // define number of tracks which are used
432 const auto nTracks = tracksTPC.size();
433 const size_t loopEnd = (mNMaxTracks < 0) ? nTracks : ((mNMaxTracks > nTracks) ? nTracks : size_t(mNMaxTracks));
434
435 // reserve memory
436 for (int i = 0; i < nBins; ++i) {
437 const int lastIdxPhi = mBufferDCA.mTSTPC.getIndexPhi(mPhiBins);
438 const int lastIdxTgl = mBufferDCA.mTSTPC.getIndexTgl(mTglBins);
439 const int lastIdxQPt = mBufferDCA.mTSTPC.getIndexqPt(mQPtBins);
440 const int lastIdxMult = mBufferDCA.mTSTPC.getIndexMult(mMultBins);
441 const int firstIdx = mBufferDCA.mTSTPC.getIndexInt();
442 int resMem = 0;
443 if (i < lastIdxPhi) {
444 resMem = loopEnd / mPhiBins;
445 } else if (i < lastIdxTgl) {
446 resMem = loopEnd / mTglBins;
447 } else if (i < lastIdxQPt) {
448 resMem = loopEnd / mQPtBins;
449 } else if (i < lastIdxMult) {
450 resMem = loopEnd / mMultBins;
451 } else {
452 resMem = loopEnd;
453 }
454 // Divide by 2 for A-C-side
455 resMem /= 2;
456 for (int type = 0; type < mAvgADCAr[i].size(); ++type) {
457 mAvgADCAr[i][type].reserve(resMem);
458 mAvgCDCAr[i][type].reserve(resMem);
459 mAvgADCAz[i][type].reserve(resMem);
460 mAvgCDCAz[i][type].reserve(resMem);
461 }
462 for (int type = 0; type < mMIPdEdxRatioQMaxA[i].size(); ++type) {
463 mMIPdEdxRatioQMaxA[i][type].reserve(resMem);
464 mMIPdEdxRatioQMaxC[i][type].reserve(resMem);
465 mMIPdEdxRatioQTotA[i][type].reserve(resMem);
466 mMIPdEdxRatioQTotC[i][type].reserve(resMem);
467 mTPCChi2A[i][type].reserve(resMem);
468 mTPCChi2C[i][type].reserve(resMem);
469 mTPCNClA[i][type].reserve(resMem);
470 mTPCNClC[i][type].reserve(resMem);
471 }
472 for (int j = 0; j < mAvgMeffA[i].size(); ++j) {
473 mAvgMeffA[i][j].reserve(resMem);
474 mAvgMeffC[i][j].reserve(resMem);
475 mAvgChi2MatchA[i][j].reserve(resMem);
476 mAvgChi2MatchC[i][j].reserve(resMem);
477 }
478 for (int j = 0; j < mITSPropertiesA[i].size(); ++j) {
479 mITSPropertiesA[i][j].reserve(resMem);
480 mITSPropertiesC[i][j].reserve(resMem);
481 }
482 for (int j = 0; j < mITSTPCDeltaPA[i].size(); ++j) {
483 mITSTPCDeltaPA[i][j].reserve(resMem);
484 mITSTPCDeltaPC[i][j].reserve(resMem);
485 }
486 for (int j = 0; j < mSigmaYZA[i].size(); ++j) {
487 mSigmaYZA[i][j].reserve(resMem);
488 mSigmaYZC[i][j].reserve(resMem);
489 }
490 for (int j = 0; j < mAvgMeffA[i].size(); ++j) {
491 mLogdEdxQTotA[i][j].reserve(resMem);
492 mLogdEdxQTotC[i][j].reserve(resMem);
493 mLogdEdxQMaxA[i][j].reserve(resMem);
494 mLogdEdxQMaxC[i][j].reserve(resMem);
495 }
496 }
497 for (int iThread = 0; iThread < mNThreads; ++iThread) {
498 const int resMem = (mNThreads > 0) ? loopEnd / mNThreads : loopEnd;
499 mBufferVals[iThread].front().reserve(loopEnd, 1);
500 mBufferVals[iThread].back().reserve(loopEnd, 0);
501 }
502
503 using timer = std::chrono::high_resolution_clock;
504 auto startTotal = timer::now();
505
506 // loop over tracks and calculate DCAs
507 if (loopEnd < nTracks) {
508 // draw random tracks
509 std::vector<size_t> ind(nTracks);
510 std::iota(ind.begin(), ind.end(), 0);
511 std::minstd_rand rng(std::time(nullptr));
512 std::shuffle(ind.begin(), ind.end(), rng);
513
514 auto myThread = [&](int iThread) {
515 for (size_t i = iThread; i < loopEnd; i += mNThreads) {
516 if (acceptTrack(tracksTPC[i])) {
517 fillDCA(tracksTPC, tracksITSTPC, vertices, i, iThread, indicesITSTPC, tracksITS, idxTPCTrackToTOFCluster, tofClusters, tpcToTRDMap, trdTracklets, trdCalibTracklets);
518 }
519 }
520 };
521
522 std::vector<std::thread> threads(mNThreads);
523 for (int i = 0; i < mNThreads; i++) {
524 threads[i] = std::thread(myThread, i);
525 }
526
527 for (auto& th : threads) {
528 th.join();
529 }
530 } else {
531 auto myThread = [&](int iThread) {
532 for (size_t i = iThread; i < loopEnd; i += mNThreads) {
533 if (acceptTrack(tracksTPC[i])) {
534 fillDCA(tracksTPC, tracksITSTPC, vertices, i, iThread, indicesITSTPC, tracksITS, idxTPCTrackToTOFCluster, tofClusters, tpcToTRDMap, trdTracklets, trdCalibTracklets);
535 }
536 }
537 };
538
539 std::vector<std::thread> threads(mNThreads);
540 for (int i = 0; i < mNThreads; i++) {
541 threads[i] = std::thread(myThread, i);
542 }
543
544 for (auto& th : threads) {
545 th.join();
546 }
547 }
548
549 // fill DCA values from buffer
550 for (const auto& vals : mBufferVals) {
551 for (int type = 0; type < vals.size(); ++type) {
552 const auto& val = vals[type];
553 const auto nPoints = val.side.size();
554 for (int i = 0; i < nPoints; ++i) {
555 const auto tglBin = val.tglBin[i];
556 const auto phiBin = val.phiBin[i];
557 const auto qPtBin = val.qPtBin[i];
558 const auto multBin = val.multBin[i];
559 const auto dcar = val.dcar[i];
560 const auto dcaz = val.dcaz[i];
561 const auto dcarW = val.dcarW[i];
562 const int binInt = nBins - 1;
563 const bool fillCombDCA = ((type == 1) && (val.dcarcomb[i] != -1) && (val.dcazcomb[i] != -1));
564 const bool fillDCAR = (type == 1) ? (dcar != -999) : true;
565 const std::array<int, 5> bins{tglBin, phiBin, qPtBin, multBin, binInt};
566 // fill bins
567 for (auto bin : bins) {
568 if (val.side[i] == Side::C) {
569 if (fillDCAR) {
570 mAvgCDCAr[bin][type].addValue(dcar, dcarW);
571 }
572 if (fillCombDCA) {
573 mAvgCDCAr[bin][2].addValue(val.dcarcomb[i], dcarW);
574 mAvgCDCAz[bin][2].addValue(val.dcazcomb[i], dcarW);
575 }
576 // fill only in case of valid value
577 if (dcaz != 0) {
578 mAvgCDCAz[bin][type].addValue(dcaz, dcarW);
579 }
580 } else {
581 if (fillDCAR) {
582 mAvgADCAr[bin][type].addValue(dcar, dcarW);
583 }
584 if (fillCombDCA) {
585 mAvgADCAr[bin][2].addValue(val.dcarcomb[i], dcarW);
586 mAvgADCAz[bin][2].addValue(val.dcazcomb[i], dcarW);
587 }
588 // fill only in case of valid value
589 if (dcaz != 0) {
590 mAvgADCAz[bin][type].addValue(dcaz, dcarW);
591 }
592 }
593 }
594 }
595 }
596 }
597
598 // calculate statistics and store values
599 // loop over TPC sides
600 for (int type = 0; type < 2; ++type) {
601 // loop over phi and tgl bins
602 for (int slice = 0; slice < nBins; ++slice) {
603 auto& bufferDCA = (type == 0) ? mBufferDCA.mTSTPC : mBufferDCA.mTSITSTPC;
604
605 const auto dcaAr = mAvgADCAr[slice][type].filterPointsMedian(mCutDCA, mCutRMS);
606 bufferDCA.mDCAr_A_Median[slice] = std::get<0>(dcaAr);
607 bufferDCA.mDCAr_A_WeightedMean[slice] = std::get<1>(dcaAr);
608 bufferDCA.mDCAr_A_RMS[slice] = std::get<2>(dcaAr);
609 bufferDCA.mDCAr_A_NTracks[slice] = std::get<3>(dcaAr);
610
611 const auto dcaAz = mAvgADCAz[slice][type].filterPointsMedian(mCutDCA, mCutRMS);
612 bufferDCA.mDCAz_A_Median[slice] = std::get<0>(dcaAz);
613 bufferDCA.mDCAz_A_WeightedMean[slice] = std::get<1>(dcaAz);
614 bufferDCA.mDCAz_A_RMS[slice] = std::get<2>(dcaAz);
615 bufferDCA.mDCAz_A_NTracks[slice] = std::get<3>(dcaAz);
616
617 const auto dcaCr = mAvgCDCAr[slice][type].filterPointsMedian(mCutDCA, mCutRMS);
618 bufferDCA.mDCAr_C_Median[slice] = std::get<0>(dcaCr);
619 bufferDCA.mDCAr_C_WeightedMean[slice] = std::get<1>(dcaCr);
620 bufferDCA.mDCAr_C_RMS[slice] = std::get<2>(dcaCr);
621 bufferDCA.mDCAr_C_NTracks[slice] = std::get<3>(dcaCr);
622
623 const auto dcaCz = mAvgCDCAz[slice][type].filterPointsMedian(mCutDCA, mCutRMS);
624 bufferDCA.mDCAz_C_Median[slice] = std::get<0>(dcaCz);
625 bufferDCA.mDCAz_C_WeightedMean[slice] = std::get<1>(dcaCz);
626 bufferDCA.mDCAz_C_RMS[slice] = std::get<2>(dcaCz);
627 bufferDCA.mDCAz_C_NTracks[slice] = std::get<3>(dcaCz);
628 // store combined ITS-TPC DCAs
629 if (type == 1) {
630 const auto dcaArComb = mAvgADCAr[slice][2].filterPointsMedian(mCutDCA, mCutRMS);
631 mBufferDCA.mDCAr_comb_A_Median[slice] = std::get<0>(dcaArComb);
632 mBufferDCA.mDCAr_comb_A_RMS[slice] = std::get<2>(dcaArComb);
633
634 const auto dcaAzCom = mAvgADCAz[slice][2].filterPointsMedian(mCutDCA, mCutRMS);
635 mBufferDCA.mDCAz_comb_A_Median[slice] = std::get<0>(dcaAzCom);
636 mBufferDCA.mDCAz_comb_A_RMS[slice] = std::get<2>(dcaAzCom);
637
638 const auto dcaCrComb = mAvgCDCAr[slice][2].filterPointsMedian(mCutDCA, mCutRMS);
639 mBufferDCA.mDCAr_comb_C_Median[slice] = std::get<0>(dcaCrComb);
640 mBufferDCA.mDCAr_comb_C_RMS[slice] = std::get<2>(dcaCrComb);
641
642 const auto dcaCzComb = mAvgCDCAz[slice][2].filterPointsMedian(mCutDCA, mCutRMS);
643 mBufferDCA.mDCAz_comb_C_Median[slice] = std::get<0>(dcaCzComb);
644 mBufferDCA.mDCAz_comb_C_RMS[slice] = std::get<2>(dcaCzComb);
645 }
646 }
647 }
648
649 // calculate matching eff
650 for (const auto& vals : mBufferVals) {
651 const auto& val = vals.front();
652 const auto nPoints = val.side.size();
653 for (int i = 0; i < nPoints; ++i) {
654 const auto tglBin = val.tglBin[i];
655 const auto phiBin = val.phiBin[i];
656 const auto qPtBin = val.qPtBin[i];
657 const auto multBin = val.multBin[i];
658 const auto dcar = val.dcar[i];
659 const auto dcaz = val.dcaz[i];
660 const auto hasITS = val.hasITS[i];
661 const auto chi2Match = val.chi2Match[i];
662 const auto dedxRatioqMax = val.dedxRatioqMax[i];
663 const auto dedxRatioqTot = val.dedxRatioqTot[i];
664 const auto sqrtChi2TPC = val.sqrtChi2TPC[i];
665 const auto nClTPC = val.nClTPC[i];
666 const int binInt = nBins - 1;
667 const Side side = val.side[i];
668 const bool isCSide = (side == Side::C);
669 const auto& bufferDCARMSR = isCSide ? mBufferDCA.mTSTPC.mDCAr_C_RMS : mBufferDCA.mTSTPC.mDCAr_A_RMS;
670 const auto& bufferDCARMSZ = isCSide ? mBufferDCA.mTSTPC.mDCAz_C_RMS : mBufferDCA.mTSTPC.mDCAz_A_RMS;
671 const auto& bufferDCAMedR = isCSide ? mBufferDCA.mTSTPC.mDCAr_C_Median : mBufferDCA.mTSTPC.mDCAr_A_Median;
672 const auto& bufferDCAMedZ = isCSide ? mBufferDCA.mTSTPC.mDCAz_C_Median : mBufferDCA.mTSTPC.mDCAz_A_Median;
673 auto& mAvgEff = isCSide ? mAvgMeffC : mAvgMeffA;
674 auto& mAvgChi2Match = isCSide ? mAvgChi2MatchC : mAvgChi2MatchA;
675 auto& mAvgmMIPdEdxRatioqMax = isCSide ? mMIPdEdxRatioQMaxC : mMIPdEdxRatioQMaxA;
676 auto& mAvgmMIPdEdxRatioqTot = isCSide ? mMIPdEdxRatioQTotC : mMIPdEdxRatioQTotA;
677 auto& mAvgmTPCChi2 = isCSide ? mTPCChi2C : mTPCChi2A;
678 auto& mAvgmTPCNCl = isCSide ? mTPCNClC : mTPCNClA;
679 auto& mAvgmdEdxRatioQMax = isCSide ? mLogdEdxQMaxC : mLogdEdxQMaxA;
680 auto& mAvgmdEdxRatioQTot = isCSide ? mLogdEdxQTotC : mLogdEdxQTotA;
681 auto& mITSProperties = isCSide ? mITSPropertiesC : mITSPropertiesA;
682 auto& mSigmaYZ = isCSide ? mSigmaYZC : mSigmaYZA;
683 auto& mITSTPCDeltaP = isCSide ? mITSTPCDeltaPC : mITSTPCDeltaPA;
684
685 const std::array<int, 5> bins{tglBin, phiBin, qPtBin, multBin, binInt};
686 // fill bins
687 for (auto bin : bins) {
688 // make DCA cut - select only good tracks
689 if ((std::abs(dcar - bufferDCAMedR[bin]) < (bufferDCARMSR[bin] * mCutRMS)) && (std::abs(dcaz - bufferDCAMedZ[bin]) < (bufferDCARMSZ[bin] * mCutRMS))) {
690 const auto gID = val.gID[i];
691 mAvgEff[bin][0].addValue(hasITS);
692 // count tpc only tracks not matched
693 if (!hasITS) {
694 mAvgEff[bin][1].addValue(hasITS);
695 mAvgEff[bin][2].addValue(hasITS);
696 }
697 // count tracks from ITS standalone and afterburner
699 mAvgEff[bin][1].addValue(hasITS);
701 mAvgEff[bin][2].addValue(hasITS);
702 }
703 if (chi2Match > 0) {
704 mAvgChi2Match[bin][0].addValue(chi2Match);
706 mAvgChi2Match[bin][1].addValue(chi2Match);
708 mAvgChi2Match[bin][2].addValue(chi2Match);
709 }
710 }
711 if (dedxRatioqMax > 0) {
712 mAvgmMIPdEdxRatioqMax[bin][0].addValue(dedxRatioqMax);
713 }
714 if (dedxRatioqTot > 0) {
715 mAvgmMIPdEdxRatioqTot[bin][0].addValue(dedxRatioqTot);
716 }
717 mAvgmTPCChi2[bin][0].addValue(sqrtChi2TPC);
718 mAvgmTPCNCl[bin][0].addValue(nClTPC);
719 if (hasITS) {
720 if (dedxRatioqMax > 0) {
721 mAvgmMIPdEdxRatioqMax[bin][1].addValue(dedxRatioqMax);
722 }
723 if (dedxRatioqTot > 0) {
724 mAvgmMIPdEdxRatioqTot[bin][1].addValue(dedxRatioqTot);
725 }
726 mAvgmTPCChi2[bin][1].addValue(sqrtChi2TPC);
727 mAvgmTPCNCl[bin][1].addValue(nClTPC);
728 }
729
730 float dedxNormQMax = val.dedxValsqMax[i].dedxNorm;
731 if (dedxNormQMax > 0) {
732 mAvgmdEdxRatioQMax[bin][0].addValue(dedxNormQMax);
733 }
734
735 float dedxNormQTot = val.dedxValsqTot[i].dedxNorm;
736 if (dedxNormQTot > 0) {
737 mAvgmdEdxRatioQTot[bin][0].addValue(dedxNormQTot);
738 }
739
740 float dedxIROCQMax = val.dedxValsqMax[i].dedxIROC;
741 if (dedxIROCQMax > 0) {
742 mAvgmdEdxRatioQMax[bin][1].addValue(dedxIROCQMax);
743 }
744
745 float dedxIROCQTot = val.dedxValsqTot[i].dedxIROC;
746 if (dedxIROCQTot > 0) {
747 mAvgmdEdxRatioQTot[bin][1].addValue(dedxIROCQTot);
748 }
749
750 float dedxOROC1QMax = val.dedxValsqMax[i].dedxOROC1;
751 if (dedxOROC1QMax > 0) {
752 mAvgmdEdxRatioQMax[bin][2].addValue(dedxOROC1QMax);
753 }
754
755 float dedxOROC1QTot = val.dedxValsqTot[i].dedxOROC1;
756 if (dedxOROC1QTot > 0) {
757 mAvgmdEdxRatioQTot[bin][2].addValue(dedxOROC1QTot);
758 }
759
760 float dedxOROC2QMax = val.dedxValsqMax[i].dedxOROC2;
761 if (dedxOROC2QMax > 0) {
762 mAvgmdEdxRatioQMax[bin][3].addValue(dedxOROC2QMax);
763 }
764
765 float dedxOROC2QTot = val.dedxValsqTot[i].dedxOROC2;
766 if (dedxOROC2QTot > 0) {
767 mAvgmdEdxRatioQTot[bin][3].addValue(dedxOROC2QTot);
768 }
769
770 float dedxOROC3QMax = val.dedxValsqMax[i].dedxOROC3;
771 if (dedxOROC3QMax > 0) {
772 mAvgmdEdxRatioQMax[bin][4].addValue(dedxOROC3QMax);
773 }
774
775 float dedxOROC3QTot = val.dedxValsqTot[i].dedxOROC3;
776 if (dedxOROC3QTot > 0) {
777 mAvgmdEdxRatioQTot[bin][4].addValue(dedxOROC3QTot);
778 }
779
780 float nClITS = val.nClITS[i];
781 if (nClITS > 0) {
782 mITSProperties[bin][0].addValue(nClITS);
783 }
784 float chi2ITS = val.chi2ITS[i];
785 if (chi2ITS > 0) {
786 mITSProperties[bin][1].addValue(chi2ITS);
787 }
788
789 float sigmay2 = val.sigmaY2[i];
790 if (sigmay2 > 0) {
791 mSigmaYZ[bin][0].addValue(sigmay2);
792 }
793 float sigmaz2 = val.sigmaZ2[i];
794 if (sigmaz2 > 0) {
795 mSigmaYZ[bin][1].addValue(sigmaz2);
796 }
797
798 float deltaP2 = val.deltaP2[i];
799 if (deltaP2 != -999) {
800 mITSTPCDeltaP[bin][0].addValue(deltaP2);
801 }
802
803 float deltaP3 = val.deltaP3[i];
804 if (deltaP3 != -999) {
805 mITSTPCDeltaP[bin][1].addValue(deltaP3);
806 }
807
808 float deltaP4 = val.deltaP4[i];
809 if (deltaP4 != -999) {
810 mITSTPCDeltaP[bin][2].addValue(deltaP4);
811 }
812 }
813 }
814 }
815 }
816
817 // store matching eff
818 for (int slice = 0; slice < nBins; ++slice) {
819 for (int i = 0; i < mAvgMeffA[slice].size(); ++i) {
820 auto& itsBuf = (i == 0) ? mBufferDCA.mITSTPCAll : ((i == 1) ? mBufferDCA.mITSTPCStandalone : mBufferDCA.mITSTPCAfterburner);
821 itsBuf.mITSTPC_A_MatchEff[slice] = mAvgMeffA[slice][i].getMean();
822 itsBuf.mITSTPC_C_MatchEff[slice] = mAvgMeffC[slice][i].getMean();
823 itsBuf.mITSTPC_A_Chi2Match[slice] = mAvgChi2MatchA[slice][i].getMean();
824 itsBuf.mITSTPC_C_Chi2Match[slice] = mAvgChi2MatchC[slice][i].getMean();
825 }
826
827 // loop over TPC and ITS-TPC tracks
828 for (int i = 0; i < mMIPdEdxRatioQMaxC[slice].size(); ++i) {
829 auto& buff = (i == 0) ? mBufferDCA.mTSTPC : mBufferDCA.mTSITSTPC;
830 buff.mMIPdEdxRatioQMaxA[slice] = mMIPdEdxRatioQMaxA[slice][i].getMean();
831 buff.mMIPdEdxRatioQMaxC[slice] = mMIPdEdxRatioQMaxC[slice][i].getMean();
832 buff.mMIPdEdxRatioQTotA[slice] = mMIPdEdxRatioQTotA[slice][i].getMean();
833 buff.mMIPdEdxRatioQTotC[slice] = mMIPdEdxRatioQTotC[slice][i].getMean();
834 buff.mTPCChi2C[slice] = mTPCChi2C[slice][i].getMean();
835 buff.mTPCChi2A[slice] = mTPCChi2A[slice][i].getMean();
836 buff.mTPCNClC[slice] = mTPCNClC[slice][i].getMean();
837 buff.mTPCNClA[slice] = mTPCNClA[slice][i].getMean();
838 }
839
840 // loop over qMax and qTot
841 for (int type = 0; type < 2; ++type) {
842 auto& logdEdxA = (type == 0) ? mLogdEdxQMaxA : mLogdEdxQTotA;
843 auto& buffer = (type == 0) ? mBufferDCA.mdEdxQMax : mBufferDCA.mdEdxQTot;
844 // fill A-side
845 buffer.mLogdEdx_A_Median[slice] = logdEdxA[slice][0].getMedian();
846 buffer.mLogdEdx_A_RMS[slice] = logdEdxA[slice][0].getStdDev();
847 buffer.mLogdEdx_A_IROC_Median[slice] = logdEdxA[slice][1].getMedian();
848 buffer.mLogdEdx_A_IROC_RMS[slice] = logdEdxA[slice][1].getStdDev();
849 buffer.mLogdEdx_A_OROC1_Median[slice] = logdEdxA[slice][2].getMedian();
850 buffer.mLogdEdx_A_OROC1_RMS[slice] = logdEdxA[slice][2].getStdDev();
851 buffer.mLogdEdx_A_OROC2_Median[slice] = logdEdxA[slice][3].getMedian();
852 buffer.mLogdEdx_A_OROC2_RMS[slice] = logdEdxA[slice][3].getStdDev();
853 buffer.mLogdEdx_A_OROC3_Median[slice] = logdEdxA[slice][4].getMedian();
854 buffer.mLogdEdx_A_OROC3_RMS[slice] = logdEdxA[slice][4].getStdDev();
855 // fill C-side
856 auto& logdEdxC = (type == 0) ? mLogdEdxQMaxC : mLogdEdxQTotC;
857 buffer.mLogdEdx_C_Median[slice] = logdEdxC[slice][0].getMedian();
858 buffer.mLogdEdx_C_RMS[slice] = logdEdxC[slice][0].getStdDev();
859 buffer.mLogdEdx_C_IROC_Median[slice] = logdEdxC[slice][1].getMedian();
860 buffer.mLogdEdx_C_IROC_RMS[slice] = logdEdxC[slice][1].getStdDev();
861 buffer.mLogdEdx_C_OROC1_Median[slice] = logdEdxC[slice][2].getMedian();
862 buffer.mLogdEdx_C_OROC1_RMS[slice] = logdEdxC[slice][2].getStdDev();
863 buffer.mLogdEdx_C_OROC2_Median[slice] = logdEdxC[slice][3].getMedian();
864 buffer.mLogdEdx_C_OROC2_RMS[slice] = logdEdxC[slice][3].getStdDev();
865 buffer.mLogdEdx_C_OROC3_Median[slice] = logdEdxC[slice][4].getMedian();
866 buffer.mLogdEdx_C_OROC3_RMS[slice] = logdEdxC[slice][4].getStdDev();
867 }
868
869 // ITS properties
870 // A-side
871 mBufferDCA.mITS_A_NCl_Median[slice] = mITSPropertiesA[slice][0].getMedian();
872 mBufferDCA.mITS_A_NCl_RMS[slice] = mITSPropertiesA[slice][0].getStdDev();
873 mBufferDCA.mSqrtITSChi2_Ncl_A_Median[slice] = mITSPropertiesA[slice][1].getMedian();
874 mBufferDCA.mSqrtITSChi2_Ncl_A_RMS[slice] = mITSPropertiesA[slice][1].getStdDev();
875 // C-side
876 mBufferDCA.mITS_C_NCl_Median[slice] = mITSPropertiesC[slice][0].getMedian();
877 mBufferDCA.mITS_C_NCl_RMS[slice] = mITSPropertiesC[slice][0].getStdDev();
878 mBufferDCA.mSqrtITSChi2_Ncl_C_Median[slice] = mITSPropertiesC[slice][1].getMedian();
879 mBufferDCA.mSqrtITSChi2_Ncl_C_RMS[slice] = mITSPropertiesC[slice][1].getStdDev();
880
881 //...
882 mBufferDCA.mITSTPCDeltaP2_A_Median[slice] = mITSTPCDeltaPA[slice][0].getMedian();
883 mBufferDCA.mITSTPCDeltaP3_A_Median[slice] = mITSTPCDeltaPA[slice][1].getMedian();
884 mBufferDCA.mITSTPCDeltaP4_A_Median[slice] = mITSTPCDeltaPA[slice][2].getMedian();
885 mBufferDCA.mITSTPCDeltaP2_C_Median[slice] = mITSTPCDeltaPC[slice][0].getMedian();
886 mBufferDCA.mITSTPCDeltaP3_C_Median[slice] = mITSTPCDeltaPC[slice][1].getMedian();
887 mBufferDCA.mITSTPCDeltaP4_C_Median[slice] = mITSTPCDeltaPC[slice][2].getMedian();
888 mBufferDCA.mITSTPCDeltaP2_A_RMS[slice] = mITSTPCDeltaPA[slice][0].getStdDev();
889 mBufferDCA.mITSTPCDeltaP3_A_RMS[slice] = mITSTPCDeltaPA[slice][1].getStdDev();
890 mBufferDCA.mITSTPCDeltaP4_A_RMS[slice] = mITSTPCDeltaPA[slice][2].getStdDev();
891 mBufferDCA.mITSTPCDeltaP2_C_RMS[slice] = mITSTPCDeltaPC[slice][0].getStdDev();
892 mBufferDCA.mITSTPCDeltaP3_C_RMS[slice] = mITSTPCDeltaPC[slice][1].getStdDev();
893 mBufferDCA.mITSTPCDeltaP4_C_RMS[slice] = mITSTPCDeltaPC[slice][2].getStdDev();
894 mBufferDCA.mTPCSigmaY2A_Median[slice] = mSigmaYZA[slice][0].getMedian();
895 mBufferDCA.mTPCSigmaZ2A_Median[slice] = mSigmaYZA[slice][1].getMedian();
896 mBufferDCA.mTPCSigmaY2C_Median[slice] = mSigmaYZC[slice][0].getMedian();
897 mBufferDCA.mTPCSigmaZ2C_Median[slice] = mSigmaYZC[slice][1].getMedian();
898 mBufferDCA.mTPCSigmaY2A_RMS[slice] = mSigmaYZA[slice][0].getStdDev();
899 mBufferDCA.mTPCSigmaZ2A_RMS[slice] = mSigmaYZA[slice][1].getStdDev();
900 mBufferDCA.mTPCSigmaY2C_RMS[slice] = mSigmaYZC[slice][0].getStdDev();
901 mBufferDCA.mTPCSigmaZ2C_RMS[slice] = mSigmaYZC[slice][1].getStdDev();
902 }
903
904 auto stop = timer::now();
905 std::chrono::duration<float> time = stop - startTotal;
906 LOGP(info, "Time series creation took {}", time.count());
907
908 // send data
909 sendOutput(pc);
910 }
911
913 {
914 for (auto& streamer : mStreamer) {
915 streamer->Close();
916 }
917 eos.services().get<ControlService>().readyToQuit(QuitRequest::Me);
918 }
919
920 void finaliseCCDB(o2::framework::ConcreteDataMatcher& matcher, void* obj) final
921 {
922 mTPCVDriftHelper.accountCCDBInputs(matcher, obj);
923 mPTHelper.accountCCDBInputs(matcher, obj);
925 if (matcher == ConcreteDataMatcher(o2::header::gDataOriginTPC, "InfoMapSecFluc", 0)) {
926 LOGP(info, "Updating TPC sector edge fluctuation info");
927 mSecEdgeFlucInfo.setFromTree(*((TTree*)obj));
928 LOGP(info, "Loaded sector edge fluctuation information with {} intervals for {} runs", mSecEdgeFlucInfo.size(), mSecEdgeFlucInfo.getNRuns());
929 }
930 }
931
932 private:
934 struct ValsdEdx {
935 float dedxNorm = 0;
936 float dedxIROC = 0;
937 float dedxOROC1 = 0;
938 float dedxOROC2 = 0;
939 float dedxOROC3 = 0;
940 };
941
942 struct FillVals {
943 void reserve(int n, int type)
944 {
945 side.reserve(n);
946 tglBin.reserve(n);
947 phiBin.reserve(n);
948 qPtBin.reserve(n);
949 multBin.reserve(n);
950 dcar.reserve(n);
951 dcaz.reserve(n);
952 dcarW.reserve(n);
953 dedxRatioqTot.reserve(n);
954 dedxRatioqMax.reserve(n);
955 sqrtChi2TPC.reserve(n);
956 nClTPC.reserve(n);
957 if (type == 1) {
958 hasITS.reserve(n);
959 chi2Match.reserve(n);
960 gID.reserve(n);
961 dedxValsqTot.reserve(n);
962 dedxValsqMax.reserve(n);
963 nClITS.reserve(n);
964 chi2ITS.reserve(n);
965 deltaP2.reserve(n);
966 deltaP3.reserve(n);
967 deltaP4.reserve(n);
968 sigmaY2.reserve(n);
969 sigmaZ2.reserve(n);
970 } else if (type == 0) {
971 dcarcomb.reserve(n);
972 dcazcomb.reserve(n);
973 }
974 }
975
976 void clear()
977 {
978 side.clear();
979 tglBin.clear();
980 phiBin.clear();
981 qPtBin.clear();
982 multBin.clear();
983 dcar.clear();
984 dcaz.clear();
985 dcarW.clear();
986 hasITS.clear();
987 chi2Match.clear();
988 dedxRatioqTot.clear();
989 dedxRatioqMax.clear();
990 sqrtChi2TPC.clear();
991 nClTPC.clear();
992 gID.clear();
993 dcarcomb.clear();
994 dcazcomb.clear();
995 nClITS.clear();
996 chi2ITS.clear();
997 dedxValsqTot.clear();
998 dedxValsqMax.clear();
999 deltaP2.clear();
1000 deltaP3.clear();
1001 deltaP4.clear();
1002 sigmaY2.clear();
1003 sigmaZ2.clear();
1004 }
1005
1006 void emplace_back(Side sideTmp, int tglBinTmp, int phiBinTmp, int qPtBinTmp, int multBinTmp, float dcarTmp, float dcazTmp, float dcarWTmp, float dedxRatioqTotTmp, float dedxRatioqMaxTmp, float sqrtChi2TPCTmp, float nClTPCTmp, o2::dataformats::GlobalTrackID::Source gIDTmp, float chi2MatchTmp, int hasITSTmp, int nClITSTmp, float chi2ITSTmp, const ValsdEdx& dedxValsqTotTmp, const ValsdEdx& dedxValsqMaxTmp, float sigmaY2Tmp, float sigmaZ2Tmp)
1007 {
1008 side.emplace_back(sideTmp);
1009 tglBin.emplace_back(tglBinTmp);
1010 phiBin.emplace_back(phiBinTmp);
1011 qPtBin.emplace_back(qPtBinTmp);
1012 multBin.emplace_back(multBinTmp);
1013 dcar.emplace_back(dcarTmp);
1014 dcaz.emplace_back(dcazTmp);
1015 dcarW.emplace_back(dcarWTmp);
1016 dedxRatioqTot.emplace_back(dedxRatioqTotTmp);
1017 dedxRatioqMax.emplace_back(dedxRatioqMaxTmp);
1018 sqrtChi2TPC.emplace_back(sqrtChi2TPCTmp);
1019 nClTPC.emplace_back(nClTPCTmp);
1020 chi2Match.emplace_back(chi2MatchTmp);
1021 hasITS.emplace_back(hasITSTmp);
1022 gID.emplace_back(gIDTmp);
1023 dedxValsqMax.emplace_back(dedxValsqMaxTmp);
1024 dedxValsqTot.emplace_back(dedxValsqTotTmp);
1025 nClITS.emplace_back(nClITSTmp);
1026 chi2ITS.emplace_back(chi2ITSTmp);
1027 sigmaY2.emplace_back(sigmaY2Tmp);
1028 sigmaZ2.emplace_back(sigmaZ2Tmp);
1029 deltaP2.emplace_back(-999);
1030 deltaP3.emplace_back(-999);
1031 deltaP4.emplace_back(-999);
1032 }
1033
1034 void setDeltaParam(float deltaP2Tmp, float deltaP3Tmp, float deltaP4Tmp)
1035 {
1036 if (!deltaP2.empty()) {
1037 deltaP2.back() = deltaP2Tmp;
1038 deltaP3.back() = deltaP3Tmp;
1039 deltaP4.back() = deltaP4Tmp;
1040 }
1041 }
1042
1043 void emplace_back_ITSTPC(Side sideTmp, int tglBinTmp, int phiBinTmp, int qPtBinTmp, int multBinTmp, float dcarTmp, float dcazTmp, float dcarWTmp, float dedxRatioqTotTmp, float dedxRatioqMaxTmp, float sqrtChi2TPCTmp, float nClTPCTmp, float dcarCombTmp, float dcazCombTmp)
1044 {
1045 side.emplace_back(sideTmp);
1046 tglBin.emplace_back(tglBinTmp);
1047 phiBin.emplace_back(phiBinTmp);
1048 qPtBin.emplace_back(qPtBinTmp);
1049 multBin.emplace_back(multBinTmp);
1050 dcar.emplace_back(dcarTmp);
1051 dcaz.emplace_back(dcazTmp);
1052 dcarW.emplace_back(dcarWTmp);
1053 dedxRatioqTot.emplace_back(dedxRatioqTotTmp);
1054 dedxRatioqMax.emplace_back(dedxRatioqMaxTmp);
1055 sqrtChi2TPC.emplace_back(sqrtChi2TPCTmp);
1056 nClTPC.emplace_back(nClTPCTmp);
1057 dcarcomb.emplace_back(dcarCombTmp);
1058 dcazcomb.emplace_back(dcazCombTmp);
1059 }
1060
1061 std::vector<Side> side;
1062 std::vector<int> tglBin;
1063 std::vector<int> phiBin;
1064 std::vector<int> qPtBin;
1065 std::vector<int> multBin;
1066 std::vector<float> dcar;
1067 std::vector<float> dcaz;
1068 std::vector<float> dcarW;
1069 std::vector<bool> hasITS;
1070 std::vector<float> chi2Match;
1071 std::vector<float> dedxRatioqTot;
1072 std::vector<float> dedxRatioqMax;
1073 std::vector<float> sqrtChi2TPC;
1074 std::vector<float> nClTPC;
1075 std::vector<float> dcarcomb;
1076 std::vector<float> dcazcomb;
1077 std::vector<ValsdEdx> dedxValsqTot;
1078 std::vector<ValsdEdx> dedxValsqMax;
1079 std::vector<int> nClITS;
1080 std::vector<float> chi2ITS;
1081 std::vector<o2::dataformats::GlobalTrackID::Source> gID;
1082 std::vector<float> deltaP2;
1083 std::vector<float> deltaP3;
1084 std::vector<float> deltaP4;
1085 std::vector<float> sigmaY2;
1086 std::vector<float> sigmaZ2;
1087 };
1088 std::shared_ptr<o2::base::GRPGeomRequest> mCCDBRequest;
1089 const bool mDisableWriter{false};
1091 const bool mUnbinnedWriter{false};
1092 const bool mTPCOnly{false};
1093 std::shared_ptr<o2::globaltracking::DataRequest> mDataRequest;
1094 int mPhiBins = SECTORSPERSIDE;
1095 int mTglBins{3};
1096 int mQPtBins{20};
1097 TimeSeriesITSTPC mBufferDCA;
1098 std::vector<std::array<RobustAverage, 3>> mAvgADCAr;
1099 std::vector<std::array<RobustAverage, 3>> mAvgCDCAr;
1100 std::vector<std::array<RobustAverage, 3>> mAvgADCAz;
1101 std::vector<std::array<RobustAverage, 3>> mAvgCDCAz;
1102 std::vector<std::array<RobustAverage, 2>> mMIPdEdxRatioQMaxA;
1103 std::vector<std::array<RobustAverage, 2>> mMIPdEdxRatioQMaxC;
1104 std::vector<std::array<RobustAverage, 2>> mMIPdEdxRatioQTotA;
1105 std::vector<std::array<RobustAverage, 2>> mMIPdEdxRatioQTotC;
1106 std::vector<std::array<RobustAverage, 2>> mTPCChi2A;
1107 std::vector<std::array<RobustAverage, 2>> mTPCChi2C;
1108 std::vector<std::array<RobustAverage, 2>> mTPCNClA;
1109 std::vector<std::array<RobustAverage, 2>> mTPCNClC;
1110 std::vector<std::array<RobustAverage, 3>> mAvgMeffA;
1111 std::vector<std::array<RobustAverage, 3>> mAvgMeffC;
1112 std::vector<std::array<RobustAverage, 3>> mAvgChi2MatchA;
1113 std::vector<std::array<RobustAverage, 3>> mAvgChi2MatchC;
1114 std::vector<std::array<RobustAverage, 10>> mLogdEdxQTotA;
1115 std::vector<std::array<RobustAverage, 10>> mLogdEdxQTotC;
1116 std::vector<std::array<RobustAverage, 10>> mLogdEdxQMaxA;
1117 std::vector<std::array<RobustAverage, 10>> mLogdEdxQMaxC;
1118 std::vector<std::array<RobustAverage, 2>> mITSPropertiesA;
1119 std::vector<std::array<RobustAverage, 2>> mITSPropertiesC;
1120 std::vector<std::array<RobustAverage, 3>> mITSTPCDeltaPA;
1121 std::vector<std::array<RobustAverage, 3>> mITSTPCDeltaPC;
1122 std::vector<std::array<RobustAverage, 2>> mSigmaYZA;
1123 std::vector<std::array<RobustAverage, 2>> mSigmaYZC;
1124 int mNMaxTracks{-1};
1125 float mMinMom{1};
1126 int mMinNCl{80};
1127 float mMaxTgl{1};
1128 float mMaxQPt{5};
1129 float mCoarseStep{1};
1130 float mFineStep{0.005};
1131 float mCutDCA{5};
1132 float mCutRMS{5};
1133 float mRefXSec{108.475};
1134 int mNThreads{1};
1135 float maxITSTPCDCAr{0.2};
1136 float maxITSTPCDCAz{10};
1137 float maxITSTPCDCAr_comb{0.2};
1138 float maxITSTPCDCAz_comb{0.2};
1139 gsl::span<const TPCClRefElem> mTPCTrackClIdx{};
1140 std::vector<std::array<FillVals, 2>> mBufferVals;
1141 uint32_t mFirstTFOrbit{0};
1142 float mTimeWindowMUS{50};
1143 float mMIPdEdx{50};
1144 std::vector<int> mNTracksWindow;
1145 std::vector<int> mNearestVtxTPC;
1146 o2::tpc::VDriftHelper mTPCVDriftHelper{};
1147 float mVDrift{2.64};
1148 float mMaxSnp{0.85};
1149 float mXCoarse{40};
1150 float mSqrt{13600};
1151 int mMultBins{20};
1152 int mMultMax{80000};
1153 PIDResponse mPID;
1154 int mMinTracksPerVertex{5};
1155 float mMaxdEdxRatio{0.3};
1156 float mMaxdEdxRegionRatio{0.5};
1157 float mSamplingFactor{0.1};
1158 bool mSampleTsallis{false};
1159 std::vector<std::mt19937> mGenerator;
1160 std::vector<std::unique_ptr<o2::utils::TreeStreamRedirector>> mStreamer;
1161 float mXOuterMatching{60};
1162 bool mUseMinBiasTrigger{false};
1163 long mTimeMS{};
1164 int mRun{};
1165 int mMaxOccupancyHistBins{912};
1166 PressureTemperatureHelper mPTHelper;
1167 o2::tpc::SectorEdgeFluctuations mSecEdgeFlucInfo;
1168
1170 bool acceptTrack(const TrackTPC& track) const { return std::abs(track.getTgl()) < mMaxTgl; }
1171
1172 bool checkTrack(const TrackTPC& track) const
1173 {
1174 const bool isGoodTrack = ((track.getNClusters() < mMinNCl) || (track.getP() < mMinMom)) ? false : true;
1175 return isGoodTrack;
1176 }
1177
1178 void fillDCA(const gsl::span<const TrackTPC> tracksTPC, const gsl::span<const o2::dataformats::TrackTPCITS> tracksITSTPC, const gsl::span<const o2::dataformats::PrimaryVertex> vertices, const int iTrk, const int iThread, const std::unordered_map<unsigned int, std::array<int, 2>>& indicesITSTPC, const gsl::span<const o2::its::TrackITS> tracksITS, const std::vector<std::tuple<int, float, float, o2::track::TrackLTIntegral, double, float, unsigned int, unsigned short>>& idxTPCTrackToTOFCluster, const gsl::span<const o2::tof::Cluster> tofClusters, const std::unordered_map<unsigned int, TRDTrackletData>& tpcToTRDMap, const gsl::span<const o2::trd::Tracklet64> trdTracklets, const gsl::span<const o2::trd::CalibratedTracklet> trdCalibTracklets)
1179 {
1180 const auto& trackFull = tracksTPC[iTrk];
1181 const bool isGoodTrack = checkTrack(trackFull);
1182
1183 // check for min bias trigger - sample flat -
1184 bool minBiasOk = false;
1185 const float factorMinBias = 0.1 * mSamplingFactor;
1186 if (mUnbinnedWriter && mUseMinBiasTrigger) {
1187 std::uniform_real_distribution<> distr(0., 1.);
1188 if (distr(mGenerator[iThread]) < factorMinBias) {
1189 minBiasOk = true;
1190 }
1191 }
1192
1193 // check if at least one check passed
1194 if (!isGoodTrack && !minBiasOk) {
1195 return;
1196 }
1197
1198 o2::track::TrackParCov track = tracksTPC[iTrk];
1199
1200 // propagate track to the DCA and fill in slice
1201 auto propagator = o2::base::Propagator::Instance();
1202
1203 // propagate track to DCA
1204 std::array<float, 2> dca;
1205 const o2::math_utils::Point3D<float> refPoint{0, 0, 0};
1206
1207 // coarse propagation
1208 if (!propagator->PropagateToXBxByBz(track, mXCoarse, mMaxSnp, mCoarseStep, mMatType)) {
1209 return;
1210 }
1211
1212 // fine propagation with Bz only
1213 if (!propagator->propagateToDCA(refPoint, track, propagator->getNominalBz(), mFineStep, mMatType, &dca)) {
1214 return;
1215 }
1216
1217 o2::track::TrackPar trackTmp(tracksTPC[iTrk]);
1218
1219 // coarse propagation to centre of IROC for phi bin
1220 if (!propagator->propagateTo(trackTmp, mRefXSec, false, mMaxSnp, mCoarseStep, mMatType)) {
1221 return;
1222 }
1223
1224 // Saturate bin indices — edge bins act as overflow (Phase 0.2 fix)
1225 const int tglBin = std::clamp(static_cast<int>(mTglBins * std::abs(trackTmp.getTgl()) / mMaxTgl) + mPhiBins,
1226 mPhiBins, mPhiBins + mTglBins - 1);
1227 const int phiBin = std::clamp(static_cast<int>(mPhiBins * trackTmp.getPhi() / o2::constants::math::TwoPI),
1228 0, mPhiBins - 1);
1229
1230 const int offsQPtBin = mPhiBins + mTglBins;
1231 const int qPtBin = std::clamp(offsQPtBin + static_cast<int>(mQPtBins * (trackTmp.getQ2Pt() + mMaxQPt) / (2 * mMaxQPt)),
1232 offsQPtBin, offsQPtBin + mQPtBins - 1);
1233 const int localMult = mNTracksWindow[iTrk];
1234
1235 const int offsMult = offsQPtBin + mQPtBins;
1236 const int multBin = std::clamp(offsMult + static_cast<int>(mMultBins * localMult / mMultMax),
1237 offsMult, offsMult + mMultBins - 1);
1238 const int nBins = getNBins();
1239
1240 float sigmaY2 = 0;
1241 float sigmaZ2 = 0;
1242 const int sector = o2::math_utils::angle2Sector(trackTmp.getPhiPos());
1243 // find possible ITS-TPC track and vertex index
1244 auto it = indicesITSTPC.find(iTrk);
1245 const auto idxITSTPC = (it != indicesITSTPC.end()) ? (it->second) : std::array<int, 2>{-1, -1};
1246
1247 // get vertex (check if vertex ID is valid). In case no vertex is assigned return nearest vertex or else default vertex
1248 const auto vertex = (idxITSTPC.back() != -1) ? vertices[idxITSTPC.back()] : ((mNearestVtxTPC[iTrk] != -1) ? vertices[mNearestVtxTPC[iTrk]] : o2::dataformats::PrimaryVertex{});
1249
1250 // calculate DCAz: (time TPC track - time vertex) * vDrift + sign_side * vertexZ
1251 const float signSide = trackFull.hasCSideClustersOnly() ? -1 : 1; // invert sign for C-side
1252 const float dcaZFromDeltaTime = (vertex.getTimeStamp().getTimeStamp() == 0) ? 0 : (o2::tpc::ParameterElectronics::Instance().ZbinWidth * trackFull.getTime0() - vertex.getTimeStamp().getTimeStamp()) * mVDrift + signSide * vertex.getZ();
1253
1254 // for weight of DCA
1255 const float resCl = std::min(trackFull.getNClusters(), static_cast<int>(Mapper::PADROWS)) / static_cast<float>(Mapper::PADROWS);
1256
1257 const float div = (resCl * track.getPt());
1258 if (div == 0) {
1259 return;
1260 }
1261
1262 const float fB = 0.2 / div;
1263 const float fA = 0.15 + 0.15; // = 0.15 with additional misalignment error
1264 const float dcarW = 1. / std::sqrt(fA * fA + fB * fB); // Weight of DCA: Rms2 ~ 0.15^2 + k/(L^2*pt) → 0.15**2 + (0.2/((NCl/152)*pt)^2);
1265
1266 // store values for TPC DCA only for A- or C-side only tracks
1267 const bool hasITSTPC = idxITSTPC.front() != -1;
1268
1269 // get ratio of chi2 in case ITS-TPC track has been found
1270 const float chi2 = hasITSTPC ? tracksITSTPC[idxITSTPC.front()].getChi2Match() : -1;
1272 // check for source in case of ITS-TPC
1273 if (hasITSTPC) {
1274 const auto src = tracksITSTPC[idxITSTPC.front()].getRefITS().getSource();
1279 }
1280 }
1281
1282 const float chi2Match = (chi2 > 0) ? std::sqrt(chi2) : -1;
1283 const float sqrtChi2TPC = (trackFull.getChi2() > 0) ? std::sqrt(trackFull.getChi2()) : 0;
1284 const float nClTPC = trackFull.getNClusters();
1285
1286 // const float dedx = mUseQMax ? track.getdEdx().dEdxMaxTPC : track.getdEdx().dEdxTotTPC;
1287 const float dedxRatioqTot = (trackFull.getdEdx().dEdxTotTPC > 0) ? (mMIPdEdx / trackFull.getdEdx().dEdxTotTPC) : -1;
1288 const float dedxRatioqMax = (trackFull.getdEdx().dEdxMaxTPC > 0) ? (mMIPdEdx / trackFull.getdEdx().dEdxMaxTPC) : -1;
1289
1290 const auto dedxQTotVars = getdEdxVars(0, trackFull);
1291 const auto dedxQMaxVars = getdEdxVars(1, trackFull);
1292
1293 // make check to avoid crash in case no or less ITS tracks have been found!
1294 const int idxITSTrack = (hasITSTPC && (gID == o2::dataformats::GlobalTrackID::Source::ITS)) ? tracksITSTPC[idxITSTPC.front()].getRefITS().getIndex() : -1;
1295 const bool idxITSCheck = (idxITSTrack != -1);
1296
1297 const int nClITS = idxITSCheck ? tracksITS[idxITSTrack].getNClusters() : -1;
1298 float chi2ITS = idxITSCheck ? tracksITS[idxITSTrack].getChi2() : -1;
1299 if ((chi2ITS > 0) && (nClITS > 0)) {
1300 chi2ITS = std::sqrt(chi2ITS / nClITS);
1301 }
1302 sigmaY2 = track.getSigmaY2();
1303 sigmaZ2 = track.getSigmaZ2();
1304 if (isGoodTrack) {
1305 if (trackFull.hasCSideClustersOnly()) {
1306 mBufferVals[iThread].front().emplace_back(Side::C, tglBin, phiBin, qPtBin, multBin, dca[0], dcaZFromDeltaTime, dcarW, dedxRatioqTot, dedxRatioqMax, sqrtChi2TPC, nClTPC, gID, chi2Match, hasITSTPC, nClITS, chi2ITS, dedxQTotVars, dedxQMaxVars, sigmaY2, sigmaZ2);
1307 } else if (trackFull.hasASideClustersOnly()) {
1308 mBufferVals[iThread].front().emplace_back(Side::A, tglBin, phiBin, qPtBin, multBin, dca[0], dcaZFromDeltaTime, dcarW, dedxRatioqTot, dedxRatioqMax, sqrtChi2TPC, nClTPC, gID, chi2Match, hasITSTPC, nClITS, chi2ITS, dedxQTotVars, dedxQMaxVars, sigmaY2, sigmaZ2);
1309 }
1310 }
1311
1312 // make propagation for ITS-TPC Track
1313 // check if the track was assigned to ITS track
1314 std::array<float, 2> dcaITSTPC{0, 0};
1315 float deltaP0 = -999;
1316 float deltaP1 = -999;
1317 float deltaP2 = -999;
1318 float deltaP3 = -999;
1319 float deltaP4 = -999;
1320 float phiITSTPCAtVertex = -999; // phi of ITS-TPC track at vertex
1321 float dcaTPCAtVertex = -999;
1322 if (hasITSTPC) {
1323 // propagate ITS-TPC track to (0,0)
1324 auto trackITSTPCTmp = tracksITSTPC[idxITSTPC.front()];
1325 // fine propagation with Bz only
1326 if (propagator->propagateToDCA(refPoint, trackITSTPCTmp, propagator->getNominalBz(), mFineStep, mMatType, &dcaITSTPC)) {
1327 // make cut on abs(DCA)
1328 if ((std::abs(dcaITSTPC[0]) < maxITSTPCDCAr) && (std::abs(dcaITSTPC[1]) < maxITSTPCDCAz)) {
1329 // store TPC only DCAs
1330 // propagate to vertex in case the track belongs to vertex
1331 const bool contributeToVertex = (idxITSTPC.back() != -1);
1332 std::array<float, 2> dcaITSTPCTmp{-1, -1};
1333
1334 if (contributeToVertex) {
1335 if (propagator->propagateToDCA(vertex.getXYZ(), trackITSTPCTmp, propagator->getNominalBz(), mFineStep, mMatType, &dcaITSTPCTmp)) {
1336 phiITSTPCAtVertex = trackITSTPCTmp.getPhi();
1337 dcaITSTPC = dcaITSTPCTmp;
1338 }
1339
1340 // propagate TPC track to vertex
1341 std::array<float, 2> dcaTPCTmp{-1, -1};
1342 if (propagator->propagateToDCA(vertex.getXYZ(), track, propagator->getNominalBz(), mFineStep, mMatType, &dcaTPCTmp)) {
1343 dcaTPCAtVertex = dcaTPCTmp[0];
1344 }
1345 }
1346
1347 // make cut around DCA to vertex due to gammas
1348 if ((std::abs(dcaITSTPCTmp[0]) < maxITSTPCDCAr_comb) && (std::abs(dcaITSTPCTmp[1]) < maxITSTPCDCAz_comb)) {
1349 // propagate TPC track to ITS track and store delta track parameters
1350 if (idxITSTrack >= 0 && track.rotate(tracksITS[idxITSTrack].getAlpha()) && propagator->propagateTo(track, trackITSTPCTmp.getX(), false, mMaxSnp, mFineStep, mMatType)) {
1351 o2::track::TrackPar trackITS(tracksITS[idxITSTrack]);
1352 const bool propITSOk = propagator->propagateTo(trackITS, trackITSTPCTmp.getX(), false, mMaxSnp, mFineStep, mMatType);
1353 if (propITSOk) {
1354 deltaP0 = track.getParam(0) - trackITS.getParam(0);
1355 deltaP1 = track.getParam(1) - trackITS.getParam(1);
1356 deltaP2 = track.getParam(2) - trackITS.getParam(2);
1357 deltaP3 = track.getParam(3) - trackITS.getParam(3);
1358 deltaP4 = track.getParam(4) - trackITS.getParam(4);
1359 mBufferVals[iThread].front().setDeltaParam(deltaP2, deltaP3, deltaP4);
1360 }
1361 }
1362 } else {
1363 dcaITSTPCTmp[0] = -1;
1364 dcaITSTPCTmp[1] = -1;
1365 }
1366
1367 if (isGoodTrack) {
1368 if (trackFull.hasCSideClustersOnly()) {
1369 mBufferVals[iThread].back().emplace_back_ITSTPC(Side::C, tglBin, phiBin, qPtBin, multBin, dcaTPCAtVertex, dcaZFromDeltaTime, dcarW, dedxRatioqTot, dedxRatioqMax, sqrtChi2TPC, nClTPC, dcaITSTPCTmp[0], dcaITSTPCTmp[1]);
1370 } else if (trackFull.hasASideClustersOnly()) {
1371 mBufferVals[iThread].back().emplace_back_ITSTPC(Side::A, tglBin, phiBin, qPtBin, multBin, dcaTPCAtVertex, dcaZFromDeltaTime, dcarW, dedxRatioqTot, dedxRatioqMax, sqrtChi2TPC, nClTPC, dcaITSTPCTmp[0], dcaITSTPCTmp[1]);
1372 }
1373 }
1374 }
1375 }
1376 }
1377
1378 if (mUnbinnedWriter && mStreamer[iThread]) {
1379 const float factorPt = mSamplingFactor;
1380 bool writeData = true;
1381 bool writeDataITSTPC = false;
1382 float weight = 0;
1383 float weightITSTPC = 0;
1384 if (mSampleTsallis) {
1385 std::uniform_real_distribution<> distr(0., 1.);
1386 writeData = o2::math_utils::Tsallis::downsampleTsallisCharged(tracksTPC[iTrk].getPt(), factorPt, mSqrt, weight, distr(mGenerator[iThread]));
1387 if (hasITSTPC) {
1388 writeDataITSTPC = o2::math_utils::Tsallis::downsampleTsallisCharged(tracksITSTPC[idxITSTPC.front()].getPt(), factorPt, mSqrt, weightITSTPC, distr(mGenerator[iThread]));
1389 }
1390 }
1391 if (writeData || writeDataITSTPC || minBiasOk) {
1392 auto clusterMask = makeClusterBitMask(trackFull);
1393 const auto& trkOrig = tracksTPC[iTrk];
1394 const bool isNearestVtx = (idxITSTPC.back() == -1); // is nearest vertex in case no vertex was found
1395 const float mx_ITS = hasITSTPC ? tracksITSTPC[idxITSTPC.front()].getX() : -1;
1396 const float pt_ITS = hasITSTPC ? tracksITSTPC[idxITSTPC.front()].getQ2Pt() : -1;
1397 const float chi2match_ITSTPC = hasITSTPC ? tracksITSTPC[idxITSTPC.front()].getChi2Match() : -1;
1398 const int nClITS = idxITSCheck ? tracksITS[idxITSTrack].getNClusters() : -1;
1399 const int chi2ITS = idxITSCheck ? tracksITS[idxITSTrack].getChi2() : -1;
1400 // D1: ITS cluster sizes (4-bit per layer, mask bit 28 = kSharedClusters)
1401 const uint32_t itsClusterSizes = idxITSCheck ? (static_cast<uint32_t>(tracksITS[idxITSTrack].getClusterSizes()) & 0x0FFFFFFFu) : 0u;
1402 const bool itsHasSharedClusters = idxITSCheck ? tracksITS[idxITSTrack].hasSharedClusters() : false;
1403 const uint32_t itsPattern = idxITSCheck ? (tracksITS[idxITSTrack].getPattern() & 0x7Fu) : 0u;
1404
1405 // D2: TRD tracklet data — native objects per layer
1406 uint8_t trdPattern = 0;
1407 uint8_t nTRDTracklets = 0;
1408 std::vector<o2::trd::Tracklet64> trdTrackletVec(6);
1409 std::vector<o2::trd::CalibratedTracklet> trdCalibVec(6);
1410 auto itTRD = tpcToTRDMap.find(iTrk);
1411 if (itTRD != tpcToTRDMap.end()) {
1412 const auto& trdData = itTRD->second;
1413 trdPattern = trdData.trdPattern;
1414 nTRDTracklets = trdData.nTRDTracklets;
1415 for (int iLay = 0; iLay < 6; ++iLay) {
1416 if (trdData.trackletIndices[iLay] >= 0) {
1417 trdTrackletVec[iLay] = trdTracklets[trdData.trackletIndices[iLay]];
1418 if (trdData.trackletIndices[iLay] < static_cast<int>(trdCalibTracklets.size())) {
1419 trdCalibVec[iLay] = trdCalibTracklets[trdData.trackletIndices[iLay]];
1420 }
1421 }
1422 }
1423 }
1424 int typeSide = 2; // A- and C-Side cluster
1425 if (trackFull.hasASideClustersOnly()) {
1426 typeSide = 0;
1427 } else if (trackFull.hasCSideClustersOnly()) {
1428 typeSide = 1;
1429 }
1430
1431 // check for TOF and propagate TPC track to TOF cluster
1432 bool hasTOFCluster = (std::get<0>(idxTPCTrackToTOFCluster[iTrk]) != -1);
1433 auto tofCl = hasTOFCluster ? tofClusters[std::get<0>(idxTPCTrackToTOFCluster[iTrk])] : o2::tof::Cluster();
1434
1435 float tpcYDeltaAtTOF = -999;
1436 float tpcZDeltaAtTOF = -999;
1437 if (hasTOFCluster) {
1438 o2::track::TrackPar trackTmpOut(tracksTPC[iTrk].getParamOut());
1439 if (trackTmpOut.rotate(o2::math_utils::sector2Angle(tofCl.getSector())) && propagator->propagateTo(trackTmpOut, tofCl.getX(), false, mMaxSnp, mFineStep, mMatType)) {
1440 tpcYDeltaAtTOF = trackTmpOut.getY() - tofCl.getY();
1441 tpcZDeltaAtTOF = signSide * (o2::tpc::ParameterElectronics::Instance().ZbinWidth * trackFull.getTime0() - vertex.getTimeStamp().getTimeStamp()) * mVDrift - trackTmpOut.getZ() + tofCl.getZ();
1442 }
1443 }
1444
1445 // get delta parameter between inner and outer
1446 float deltaTPCParamInOutTgl = trackFull.getTgl() - trackFull.getParamOut().getTgl();
1447 float deltaTPCParamInOutQPt = trackFull.getQ2Pt() - trackFull.getParamOut().getQ2Pt();
1448
1449 // propagate TPC track and ITS-TPC track to outer matching at 60cm
1450 float deltaP0OuterITS = -999;
1451 float deltaP1OuterITS = -999;
1452 float deltaP2OuterITS = -999;
1453 float deltaP3OuterITS = -999;
1454 float deltaP4OuterITS = -999;
1455 if (idxITSCheck) {
1456 o2::track::TrackPar trackTmpOut(tracksITS[idxITSTrack].getParamOut());
1457 const bool propITSOk = propagator->propagateTo(trackTmpOut, mXOuterMatching, false, mMaxSnp, mCoarseStep, mMatType);
1458 if (propITSOk && trackTmp.rotate(trackTmpOut.getAlpha())) {
1459 const bool propTPCOk = propagator->propagateTo(trackTmp, mXOuterMatching, false, mMaxSnp, mCoarseStep, mMatType);
1460 if (propTPCOk) {
1461 // store delta parameters
1462 deltaP0OuterITS = trackTmp.getParam(0) - trackTmpOut.getParam(0);
1463 deltaP1OuterITS = trackTmp.getParam(1) - trackTmpOut.getParam(1);
1464 deltaP2OuterITS = trackTmp.getParam(2) - trackTmpOut.getParam(2);
1465 deltaP3OuterITS = trackTmp.getParam(3) - trackTmpOut.getParam(3);
1466 deltaP4OuterITS = trackTmp.getParam(4) - trackTmpOut.getParam(4);
1467 }
1468 }
1469 }
1470 // triggerMask bits:
1471 // 0x1: flat minimum-bias stream
1472 // 0x2: Tsallis stream sampled with TPC-only pT
1473 // 0x4: Tsallis stream sampled with ITS-TPC combined pT
1474 const int triggerMask = 0x1 * minBiasOk + 0x2 * writeData + 0x4 * writeDataITSTPC;
1475
1476 float deltaP2ConstrVtx = -999;
1477 float deltaP3ConstrVtx = -999;
1478 float deltaP4ConstrVtx = -999;
1479
1480 // cov of TPC track constrained at vertex
1481 float covTPCConstrVtxP2 = -999;
1482 float covTPCConstrVtxP3 = -999;
1483 float covTPCConstrVtxP4 = -999;
1484
1485 // cov of ITS-TPC track at vertex
1486 float covITSTPCConstrVtxP2 = -999;
1487 float covITSTPCConstrVtxP3 = -999;
1488 float covITSTPCConstrVtxP4 = -999;
1489
1490 float covTPCAtVertex0 = -999;
1491 float covTPCAtVertex1 = -999;
1492
1493 const bool contributeToVertex = (idxITSTPC.back() != -1);
1494 if (hasITSTPC && contributeToVertex) {
1495 o2::track::TrackParCov trackITSTPCTmp = tracksITSTPC[idxITSTPC.front()];
1496 std::array<float, 2> dcaITSTPCTmp{-1, -1};
1497 if (propagator->propagateToDCA(vertex.getXYZ(), trackITSTPCTmp, propagator->getNominalBz(), mFineStep, mMatType, &dcaITSTPCTmp)) {
1498 o2::track::TrackParCov trackTPC = tracksTPC[iTrk];
1499 if (trackTPC.rotate(trackITSTPCTmp.getAlpha()) && propagator->propagateTo(trackTPC, trackITSTPCTmp.getX(), false, mMaxSnp, mFineStep, mMatType)) {
1500 // store covariance of TPC track at vertex
1501 covTPCAtVertex0 = trackTPC.getCovarElem(0, 0);
1502 covTPCAtVertex1 = trackTPC.getCovarElem(1, 1);
1503
1504 trackTPC.update(vertex);
1505 deltaP2ConstrVtx = trackTPC.getParam(2) - trackITSTPCTmp.getParam(2);
1506 deltaP3ConstrVtx = trackTPC.getParam(3) - trackITSTPCTmp.getParam(3);
1507 deltaP4ConstrVtx = trackTPC.getParam(4) - trackITSTPCTmp.getParam(4);
1508 covTPCConstrVtxP2 = trackTPC.getCovarElem(2, 2);
1509 covTPCConstrVtxP3 = trackTPC.getCovarElem(3, 3);
1510 covTPCConstrVtxP4 = trackTPC.getCovarElem(4, 4);
1511 covITSTPCConstrVtxP2 = trackITSTPCTmp.getCovarElem(2, 2);
1512 covITSTPCConstrVtxP3 = trackITSTPCTmp.getCovarElem(3, 3);
1513 covITSTPCConstrVtxP4 = trackITSTPCTmp.getCovarElem(4, 4);
1514 }
1515 }
1516 }
1517 double vertexTime = vertex.getTimeStamp().getTimeStamp();
1518 double trackTime0 = trackFull.getTime0();
1519 *mStreamer[iThread] << "treeTimeSeries"
1520 // DCAs
1521 << "triggerMask=" << triggerMask
1522 << "factorMinBias=" << factorMinBias
1523 << "factorPt=" << factorPt
1524 << "weight=" << weight
1525 << "weight_ITSTPC=" << weightITSTPC
1526 << "dcar_tpc_vertex=" << dcaTPCAtVertex
1527 << "dcar_tpc=" << dca[0]
1528 << "dcaz_tpc=" << dca[1]
1529 << "dcar_itstpc=" << dcaITSTPC[0]
1530 << "dcaz_itstpc=" << dcaITSTPC[1]
1531 << "dcarW=" << dcarW
1532 << "dcaZFromDeltaTime=" << dcaZFromDeltaTime
1533 << "hasITSTPC=" << hasITSTPC
1534 // vertex
1535 << "vertex_x=" << vertex.getX()
1536 << "vertex_y=" << vertex.getY()
1537 << "vertex_z=" << vertex.getZ()
1538 << "vertex_time=" << vertex.getTimeStamp().getTimeStamp()
1539 << "vertex_nContributors=" << vertex.getNContributors()
1540 << "isNearestVertex=" << isNearestVtx
1541 // tpc track properties
1542 << "pt=" << trkOrig.getPt()
1543 << "qpt_ITSTPC=" << pt_ITS
1544 << "tpc_timebin=" << trkOrig.getTime0()
1545 << "qpt=" << trkOrig.getParam(4)
1546 << "ncl=" << trkOrig.getNClusters()
1547 << "ncl_shared=" << trkOrig.getNClusters()
1548 << "tgl=" << trkOrig.getTgl()
1549 << "side_type=" << typeSide
1550 << "phi=" << trkOrig.getPhi()
1551 << "clusterMask=" << clusterMask
1552 << "dedxTPC=" << trkOrig.getdEdx()
1553 << "chi2=" << trkOrig.getChi2()
1554 << "mX=" << trkOrig.getX()
1555 << "mX_ITS=" << mx_ITS
1556 << "nClITS=" << nClITS
1557 << "chi2ITS=" << chi2ITS
1558 << "itsClusterSizes=" << itsClusterSizes
1559 << "itsHasSharedClusters=" << itsHasSharedClusters
1560 << "itsPattern=" << itsPattern
1561 // D2: TRD tracklet data
1562 << "trdPattern=" << trdPattern
1563 << "nTRDTracklets=" << nTRDTracklets
1564 << "trdTracklets=" << trdTrackletVec
1565 << "trdCalibTracklets=" << trdCalibVec
1566 << "chi2match_ITSTPC=" << chi2match_ITSTPC
1567 << "PID=" << trkOrig.getPID().getID()
1568 // TPC cov at vertex (without vertex constrained)
1569 << "covTPCAtVertex0=" << covTPCAtVertex0
1570 << "covTPCAtVertex1=" << covTPCAtVertex1
1571 // TPC cov at vertex (with vertex constrained)
1572 << "covTPCConstrVtxP2=" << covTPCConstrVtxP2
1573 << "covTPCConstrVtxP3=" << covTPCConstrVtxP3
1574 << "covTPCConstrVtxP4=" << covTPCConstrVtxP4
1575 // ITS-TPC cov at vertex (with vertex constrained)
1576 << "covITSTPCConstrVtxP2=" << covITSTPCConstrVtxP2
1577 << "covITSTPCConstrVtxP3=" << covITSTPCConstrVtxP3
1578 << "covITSTPCConstrVtxP4=" << covITSTPCConstrVtxP4
1579 // delta Parameter at vertex with TPC track constrained at vertex
1580 << "deltaP2ConstrVtx=" << deltaP2ConstrVtx
1581 << "deltaP3ConstrVtx=" << deltaP3ConstrVtx
1582 << "deltaP4ConstrVtx=" << deltaP4ConstrVtx
1583 //
1584 << "deltaPar0=" << deltaP0
1585 << "deltaPar1=" << deltaP1
1586 << "deltaPar2=" << deltaP2
1587 << "deltaPar3=" << deltaP3
1588 << "deltaPar4=" << deltaP4
1589 << "sigmaY2=" << sigmaY2
1590 << "sigmaZ2=" << sigmaZ2
1591 // meta
1592 << "mult=" << mNTracksWindow[iTrk]
1593 << "time_window_mult=" << mTimeWindowMUS
1594 << "firstTFOrbit=" << mFirstTFOrbit
1595 << "timeMS=" << mTimeMS
1596 << "run=" << mRun
1597 << "mVDrift=" << mVDrift
1598 << "its_flag=" << int(gID)
1599 << "sqrtChi2Match=" << chi2Match
1600 // TOF cluster
1601 << "tpcYDeltaAtTOF=" << tpcYDeltaAtTOF
1602 << "tpcZDeltaAtTOF=" << tpcZDeltaAtTOF
1603 << "mDXatTOF=" << std::get<1>(idxTPCTrackToTOFCluster[iTrk])
1604 << "mDZatTOF=" << std::get<2>(idxTPCTrackToTOFCluster[iTrk])
1605 << "mTOFLength=" << std::get<3>(idxTPCTrackToTOFCluster[iTrk])
1606 << "mTOFSignal=" << std::get<4>(idxTPCTrackToTOFCluster[iTrk])
1607 << "mDeltaTTOFTPC=" << std::get<5>(idxTPCTrackToTOFCluster[iTrk])
1608 << "vertexTime=" << vertexTime
1609 << "trackTime0=" << trackTime0
1610 << "TOFmask=" << std::get<6>(idxTPCTrackToTOFCluster[iTrk])
1611 << "TOFchannel=" << std::get<7>(idxTPCTrackToTOFCluster[iTrk])
1612 // TPC delta param
1613 << "deltaTPCParamInOutTgl=" << deltaTPCParamInOutTgl
1614 << "deltaTPCParamInOutQPt=" << deltaTPCParamInOutQPt
1615 // delta parameter between ITS-TPC - TPC at 60 cm
1616 << "deltaP0OuterITS=" << deltaP0OuterITS
1617 << "deltaP1OuterITS=" << deltaP1OuterITS
1618 << "deltaP2OuterITS=" << deltaP2OuterITS
1619 << "deltaP3OuterITS=" << deltaP3OuterITS
1620 << "deltaP4OuterITS=" << deltaP4OuterITS
1621 << "mXOuterMatching=" << mXOuterMatching
1622 // phi of ITS-TPC track at vertex
1623 << "phiITSTPCAtVertex=" << phiITSTPCAtVertex
1624 << "\n";
1625 }
1626 }
1627 }
1628
1629 void sendOutput(ProcessingContext& pc)
1630 {
1631 mBufferDCA.mTSTPC.setStartTime(mTimeMS);
1632 mBufferDCA.mTSITSTPC.setStartTime(mTimeMS);
1633 pc.outputs().snapshot(Output{header::gDataOriginTPC, getDataDescriptionTimeSeries()}, mBufferDCA);
1634 // in case of ROOT output also store the TFinfo in the TTree
1635 if (!mDisableWriter) {
1638 pc.outputs().snapshot(Output{header::gDataOriginTPC, getDataDescriptionTPCTimeSeriesTFId()}, tfinfo);
1639 }
1640 }
1641
1643 void findNearesVertex(const gsl::span<const TrackTPC> tracksTPC, const gsl::span<const o2::dataformats::PrimaryVertex> vertices)
1644 {
1645 // create list of time bins of tracks
1646 const int nVertices = vertices.size();
1647
1648 const int nTracks = tracksTPC.size();
1649 mNearestVtxTPC.clear();
1650 mNearestVtxTPC.resize(nTracks);
1651
1652 // in case no vertices are found
1653 if (!nVertices) {
1654 std::fill(mNearestVtxTPC.begin(), mNearestVtxTPC.end(), -1);
1655 return;
1656 }
1657
1658 // store timestamps of vertices. Assume vertices are already sorted in time!
1659 std::vector<float> times_vtx;
1660 times_vtx.reserve(nVertices);
1661 for (const auto& vtx : vertices) {
1662 times_vtx.emplace_back(vtx.getTimeStamp().getTimeStamp());
1663 }
1664
1665 // loop over tpc tracks and find nearest vertex
1666 auto myThread = [&](int iThread) {
1667 for (int i = iThread; i < nTracks; i += mNThreads) {
1668 const float timeTrack = o2::tpc::ParameterElectronics::Instance().ZbinWidth * tracksTPC[i].getTime0();
1669 const auto lower = std::lower_bound(times_vtx.begin(), times_vtx.end(), timeTrack);
1670 int closestVtx = std::distance(times_vtx.begin(), lower);
1671 // if value is out of bounds use last value
1672 if (closestVtx == nVertices) {
1673 closestVtx -= 1;
1674 } else if (closestVtx > 0) {
1675 // if idx > 0 check preceeding value
1676 double diff1 = std::abs(timeTrack - *lower);
1677 double diff2 = std::abs(timeTrack - *(lower - 1));
1678 if (diff2 < diff1) {
1679 closestVtx -= 1;
1680 }
1681 }
1682 mNearestVtxTPC[i] = closestVtx;
1683 }
1684 };
1685
1686 std::vector<std::thread> threads(mNThreads);
1687 for (int i = 0; i < mNThreads; i++) {
1688 threads[i] = std::thread(myThread, i);
1689 }
1690
1691 // wait for the threads to finish
1692 for (auto& th : threads) {
1693 th.join();
1694 }
1695 }
1696
1698 std::vector<bool> makeClusterBitMask(const TrackTPC& track) const
1699 {
1700 std::vector<bool> tpcClusterMask(Mapper::PADROWS, false);
1701 const int nCl = track.getNClusterReferences();
1702 for (int j = 0; j < nCl; ++j) {
1703 uint8_t sector, padrow;
1704 uint32_t clusterIndexInRow;
1705 track.getClusterReference(mTPCTrackClIdx, j, sector, padrow, clusterIndexInRow);
1706 tpcClusterMask[padrow] = true;
1707 }
1708 return tpcClusterMask;
1709 }
1710
1712 void findNNeighbourTracks(const gsl::span<const TrackTPC> tracksTPC)
1713 {
1714 const float tpcTBinMUS = o2::tpc::ParameterElectronics::Instance().ZbinWidth; // 0.199606f; time bin in MUS
1715 const float windowTimeBins = mTimeWindowMUS / tpcTBinMUS; // number of neighbouring time bins to check
1716
1717 // create list of time bins of tracks
1718 std::vector<float> times;
1719 const int nTracks = tracksTPC.size();
1720 times.reserve(nTracks);
1721 for (const auto& trk : tracksTPC) {
1722 times.emplace_back(trk.getTime0());
1723 }
1724 std::sort(times.begin(), times.end());
1725
1726 mNTracksWindow.clear();
1727 mNTracksWindow.resize(nTracks);
1728
1729 // loop over tpc tracks and count number of neighouring tracks
1730 auto myThread = [&](int iThread) {
1731 for (int i = iThread; i < nTracks; i += mNThreads) {
1732 const float t0 = tracksTPC[i].getTime0();
1733 const auto upperV0 = std::upper_bound(times.begin(), times.end(), t0 + windowTimeBins);
1734 const auto lowerV0 = std::lower_bound(times.begin(), times.end(), t0 - windowTimeBins);
1735 const int nMult = std::distance(times.begin(), upperV0) - std::distance(times.begin(), lowerV0);
1736 mNTracksWindow[i] = nMult;
1737 }
1738 };
1739
1740 std::vector<std::thread> threads(mNThreads);
1741 for (int i = 0; i < mNThreads; i++) {
1742 threads[i] = std::thread(myThread, i);
1743 }
1744
1745 // wait for the threads to finish
1746 for (auto& th : threads) {
1747 th.join();
1748 }
1749 }
1750
1751 std::unordered_map<unsigned int, int> processVertices(const gsl::span<const o2::dataformats::PrimaryVertex> vertices, const gsl::span<const o2::dataformats::VtxTrackIndex> primMatchedTracks, const gsl::span<const o2::dataformats::VtxTrackRef> primMatchedTracksRef, const RecoContainer& recoData)
1752 {
1753 // storing collision vertex to ITS-TPC track index
1754 std::unordered_map<unsigned int, int> indicesITSTPC_vtx; // ITS-TPC track index -> collision vertex ID
1755
1756 std::unordered_map<int, int> nContributors_ITS; // ITS: vertex ID -> n contributors
1757 std::unordered_map<int, int> nContributors_ITSTPC; // ITS-TPC (and ITS-TPC-TRD, ITS-TPC-TOF, ITS-TPC-TRD-TOF): vertex ID -> n contributors
1758 std::unordered_map<int, int> nContributors_TRD; // ITS-TPC-TRD (and ITS-TPC-TRD-TOF): vertex ID -> n TRD-matched PV contributors
1759
1760 // loop over collisions
1761 if (!vertices.empty()) {
1762 for (const auto& ref : primMatchedTracksRef) {
1763 // loop over ITS and ITS-TPC sources
1764 const std::array<TrkSrc, 5> sources = {TrkSrc::ITSTPC, TrkSrc::ITSTPCTRD, TrkSrc::ITSTPCTOF, TrkSrc::ITSTPCTRDTOF, TrkSrc::ITS};
1765 for (auto source : sources) {
1766 const int vID = ref.getVtxID(); // vertex ID
1767 const int firstEntry = ref.getFirstEntryOfSource(source);
1768 const int nEntries = ref.getEntriesOfSource(source);
1769 // loop over all tracks belonging to the vertex
1770 for (int i = 0; i < nEntries; ++i) {
1771 const auto& matchedTrk = primMatchedTracks[i + firstEntry];
1772 bool pvCont = matchedTrk.isPVContributor();
1773 if (pvCont) {
1774 // store index of ITS-TPC track container and vertex ID
1775 auto refITSTPC = recoData.getSingleDetectorRefs(matchedTrk)[TrkSrc::ITSTPC];
1776 if (refITSTPC.isIndexSet()) {
1777 indicesITSTPC_vtx[refITSTPC] = vID;
1778 ++nContributors_ITSTPC[vID];
1779 // count TRD-matched PV contributors
1780 if (source == TrkSrc::ITSTPCTRD || source == TrkSrc::ITSTPCTRDTOF) {
1781 ++nContributors_TRD[vID];
1782 }
1783 } else {
1784 ++nContributors_ITS[vID];
1785 }
1786 }
1787 }
1788 }
1789 }
1790 }
1791
1792 // calculate statistics
1793 std::array<RobustAverage, 4> avgVtxITS;
1794 std::array<RobustAverage, 4> avgVtxITSTPC;
1795 for (int i = 0; i < avgVtxITS.size(); ++i) {
1796 avgVtxITS[i].reserve(vertices.size());
1797 avgVtxITSTPC[i].reserve(vertices.size());
1798 }
1799 for (int ivtx = 0; ivtx < vertices.size(); ++ivtx) {
1800 const auto& vtx = vertices[ivtx];
1801 const float itsFrac = nContributors_ITS[ivtx] / static_cast<float>(vtx.getNContributors());
1802 const float itstpcFrac = (nContributors_ITS[ivtx] + nContributors_ITSTPC[ivtx]) / static_cast<float>(vtx.getNContributors());
1803
1804 const float itsMin = 0.2;
1805 const float itsMax = 0.8;
1806 if ((itsFrac > itsMin) && (itsFrac < itsMax)) {
1807 avgVtxITS[0].addValue(vtx.getX());
1808 avgVtxITS[1].addValue(vtx.getY());
1809 avgVtxITS[2].addValue(vtx.getZ());
1810 avgVtxITS[3].addValue(vtx.getNContributors());
1811 }
1812
1813 const float itstpcMax = 0.95;
1814 if (itstpcFrac < itstpcMax) {
1815 avgVtxITSTPC[0].addValue(vtx.getX());
1816 avgVtxITSTPC[1].addValue(vtx.getY());
1817 avgVtxITSTPC[2].addValue(vtx.getZ());
1818 avgVtxITSTPC[3].addValue(vtx.getNContributors());
1819 }
1820 }
1821
1822 // ITS
1823 mBufferDCA.nPrimVertices_ITS.front() = avgVtxITS[3].getValues().size();
1824 mBufferDCA.nVertexContributors_ITS_Median.front() = avgVtxITS[3].getMedian();
1825 mBufferDCA.nVertexContributors_ITS_RMS.front() = avgVtxITS[3].getStdDev();
1826 mBufferDCA.vertexX_ITS_Median.front() = avgVtxITS[0].getMedian();
1827 mBufferDCA.vertexY_ITS_Median.front() = avgVtxITS[1].getMedian();
1828 mBufferDCA.vertexZ_ITS_Median.front() = avgVtxITS[2].getMedian();
1829 mBufferDCA.vertexX_ITS_RMS.front() = avgVtxITS[0].getStdDev();
1830 mBufferDCA.vertexY_ITS_RMS.front() = avgVtxITS[1].getStdDev();
1831 mBufferDCA.vertexZ_ITS_RMS.front() = avgVtxITS[2].getStdDev();
1832
1833 // ITS-TPC
1834 mBufferDCA.nPrimVertices_ITSTPC.front() = avgVtxITSTPC[3].getValues().size();
1835 mBufferDCA.nVertexContributors_ITSTPC_Median.front() = avgVtxITSTPC[3].getMedian();
1836 mBufferDCA.nVertexContributors_ITSTPC_RMS.front() = avgVtxITSTPC[3].getStdDev();
1837 mBufferDCA.vertexX_ITSTPC_Median.front() = avgVtxITSTPC[0].getMedian();
1838 mBufferDCA.vertexY_ITSTPC_Median.front() = avgVtxITSTPC[1].getMedian();
1839 mBufferDCA.vertexZ_ITSTPC_Median.front() = avgVtxITSTPC[2].getMedian();
1840 mBufferDCA.vertexX_ITSTPC_RMS.front() = avgVtxITSTPC[0].getStdDev();
1841 mBufferDCA.vertexY_ITSTPC_RMS.front() = avgVtxITSTPC[1].getStdDev();
1842 mBufferDCA.vertexZ_ITSTPC_RMS.front() = avgVtxITSTPC[2].getStdDev();
1843
1844 // TRD matching fraction (summed over all vertices in this TF)
1845 int sumITSTPCBased = 0;
1846 int sumWithTRD = 0;
1847 for (int ivtx = 0; ivtx < vertices.size(); ++ivtx) {
1848 sumITSTPCBased += nContributors_ITSTPC[ivtx];
1849 sumWithTRD += nContributors_TRD[ivtx];
1850 }
1851 mBufferDCA.nITSTPCBasedPVContributors.front() = sumITSTPCBased;
1852 mBufferDCA.nITSTPCWithTRDPVContributors.front() = sumWithTRD;
1853 mBufferDCA.fracTRD.front() = (sumITSTPCBased > 0) ? static_cast<float>(sumWithTRD) / sumITSTPCBased : std::nanf("");
1854
1855 // quantiles and truncated mean
1856 RobustAverage avg(vertices.size(), false);
1857 for (const auto& vtx : vertices) {
1858 if (vtx.getNContributors() > mMinTracksPerVertex) {
1859 // transform by n^0.5 to get more flat distribution
1860 avg.addValue(std::sqrt(vtx.getNContributors()));
1861 }
1862 }
1863
1864 // nPrimVertices_Quantiles
1865 int sizeQ = mBufferDCA.nVertexContributors_Quantiles.size();
1866 const int nBinsQ = 20;
1867 if (sizeQ >= (nBinsQ + 3)) {
1868 for (int iq = 0; iq < nBinsQ; ++iq) {
1869 const float quantile = (iq + 1) / static_cast<float>(nBinsQ);
1870 const float val = avg.getQuantile(quantile, 1);
1871 mBufferDCA.nVertexContributors_Quantiles[iq] = val * val;
1872 }
1873 const float tr0 = avg.getTrunctedMean(0.05, 0.95);
1874 const float tr1 = avg.getTrunctedMean(0.1, 0.9);
1875 const float tr2 = avg.getTrunctedMean(0.2, 0.8);
1876 mBufferDCA.nVertexContributors_Quantiles[sizeQ - 3] = tr0 * tr0;
1877 mBufferDCA.nVertexContributors_Quantiles[sizeQ - 2] = tr1 * tr1;
1878 mBufferDCA.nVertexContributors_Quantiles[sizeQ - 1] = tr2 * tr2;
1879 }
1880 mBufferDCA.nPrimVertices.front() = vertices.size();
1881
1882 return indicesITSTPC_vtx;
1883 }
1884
1886 int getNBins() const { return mBufferDCA.mTSTPC.getNBins(); }
1887
1888 ValsdEdx getdEdxVars(bool useQMax, const TrackTPC& track) const
1889 {
1890 const float dedx = useQMax ? track.getdEdx().dEdxMaxTPC : track.getdEdx().dEdxTotTPC;
1891 const float dedxRatioNorm = mPID.getExpectedSignal(track, o2::track::PID::ID(o2::track::PID::Pion)) / dedx;
1892 float dedxNorm = (dedxRatioNorm > 0) ? std::log(mPID.getExpectedSignal(track, o2::track::PID::ID(o2::track::PID::Pion)) / dedx) : -1;
1893 // restrict to specified range
1894 if (std::abs(dedxNorm) > mMaxdEdxRatio) {
1895 dedxNorm = -1;
1896 }
1897
1898 // get log(dedxRegion / dedx)
1899 float dedxIROC = -1;
1900 float dedxOROC1 = -1;
1901 float dedxOROC2 = -1;
1902 float dedxOROC3 = -1;
1903 if (dedx > 0) {
1904 dedxIROC = useQMax ? track.getdEdx().dEdxMaxIROC : track.getdEdx().dEdxTotIROC;
1905 dedxOROC1 = useQMax ? track.getdEdx().dEdxMaxOROC1 : track.getdEdx().dEdxTotOROC1;
1906 dedxOROC2 = useQMax ? track.getdEdx().dEdxMaxOROC2 : track.getdEdx().dEdxTotOROC2;
1907 dedxOROC3 = useQMax ? track.getdEdx().dEdxMaxOROC3 : track.getdEdx().dEdxTotOROC3;
1908 dedxIROC /= dedx;
1909 dedxOROC1 /= dedx;
1910 dedxOROC2 /= dedx;
1911 dedxOROC3 /= dedx;
1912 dedxIROC = (dedxIROC > 0) ? std::log(dedxIROC) : -1;
1913 dedxOROC1 = (dedxOROC1 > 0) ? std::log(dedxOROC1) : -1;
1914 dedxOROC2 = (dedxOROC2 > 0) ? std::log(dedxOROC2) : -1;
1915 dedxOROC3 = (dedxOROC3 > 0) ? std::log(dedxOROC3) : -1;
1916
1917 // restrict to specified range
1918 if (std::abs(dedxIROC) > mMaxdEdxRegionRatio) {
1919 dedxIROC = -1;
1920 }
1921 if (std::abs(dedxOROC1) > mMaxdEdxRegionRatio) {
1922 dedxOROC1 = -1;
1923 }
1924 if (std::abs(dedxOROC2) > mMaxdEdxRegionRatio) {
1925 dedxOROC2 = -1;
1926 }
1927 if (std::abs(dedxOROC3) > mMaxdEdxRegionRatio) {
1928 dedxOROC3 = -1;
1929 }
1930 }
1931 return ValsdEdx{dedxNorm, dedxIROC, dedxOROC1, dedxOROC2, dedxOROC3};
1932 }
1933};
1934
1935o2::framework::DataProcessorSpec getTPCTimeSeriesSpec(const bool disableWriter, const o2::base::Propagator::MatCorrType matType, const bool enableUnbinnedWriter, GTrackID::mask_t src)
1936{
1937 auto dataRequest = std::make_shared<DataRequest>();
1938 bool useMC = false;
1939 GTrackID::mask_t srcTracks = GTrackID::getSourcesMask("TPC,ITS,ITS-TPC,ITS-TPC-TRD,ITS-TPC-TOF,ITS-TPC-TRD-TOF") & src;
1940 dataRequest->requestTracks(srcTracks, useMC);
1941 if (src[GTrackID::TPC]) {
1942 dataRequest->requestClusters(GTrackID::getSourcesMask("TPC"), useMC);
1943 }
1944 // D2: request TRD tracklets for tracks with TRD contribution
1945 if (srcTracks[GTrackID::ITSTPCTRD] || srcTracks[GTrackID::ITSTPCTRDTOF]) {
1946 dataRequest->requestTRDTracklets(useMC);
1947 }
1948
1949 bool tpcOnly = srcTracks == GTrackID::getSourcesMask("TPC");
1950 if (srcTracks.any() && !tpcOnly) {
1951 dataRequest->requestFT0RecPoints(useMC);
1952 dataRequest->requestPrimaryVertices(useMC);
1953 }
1954
1955 const bool enableAskMatLUT = matType == o2::base::Propagator::MatCorrType::USEMatCorrLUT;
1956 auto ccdbRequest = std::make_shared<o2::base::GRPGeomRequest>(!disableWriter, // orbitResetTime
1957 false, // GRPECS=true for nHBF per TF
1958 false, // GRPLHCIF
1959 true, // GRPMagField
1960 enableAskMatLUT, // askMatLUT
1962 dataRequest->inputs,
1963 true,
1964 true);
1965
1966 o2::tpc::VDriftHelper::requestCCDBInputs(dataRequest->inputs);
1968 dataRequest->inputs.emplace_back("tpcSecFlucInfo", o2::header::gDataOriginTPC, "InfoMapSecFluc", 0, Lifetime::Condition, ccdbParamSpec(CDBTypeMap.at(CDBType::CalSecEdgeInfo), {}, 1));
1969
1970 std::vector<OutputSpec> outputs;
1971 outputs.emplace_back(o2::header::gDataOriginTPC, getDataDescriptionTimeSeries(), 0, Lifetime::Sporadic);
1972 if (!disableWriter) {
1973 outputs.emplace_back(o2::header::gDataOriginTPC, getDataDescriptionTPCTimeSeriesTFId(), 0, Lifetime::Sporadic);
1974 }
1975
1976 return DataProcessorSpec{
1977 "tpc-time-series",
1978 dataRequest->inputs,
1979 outputs,
1980 AlgorithmSpec{adaptFromTask<TPCTimeSeries>(ccdbRequest, disableWriter, matType, enableUnbinnedWriter, tpcOnly, dataRequest)},
1981 Options{
1982 {"min-momentum", VariantType::Float, 0.2f, {"Minimum momentum of the tracks"}},
1983 {"min-cluster", VariantType::Int, 80, {"Minimum number of clusters of the tracks"}},
1984 {"max-tgl", VariantType::Float, 1.4f, {"Maximum accepted tgl of the tracks"}},
1985 {"max-qPt", VariantType::Float, 5.f, {"Maximum abs(qPt) bin"}},
1986 {"max-snp", VariantType::Float, 0.85f, {"Maximum sinus(phi) for propagation"}},
1987 {"coarse-step", VariantType::Float, 5.f, {"Coarse step during track propagation"}},
1988 {"fine-step", VariantType::Float, 2.f, {"Fine step during track propagation"}},
1989 {"mX-coarse", VariantType::Float, 40.f, {"Perform coarse propagation up to this mx"}},
1990 {"max-tracks", VariantType::Int, -1, {"Number of maximum tracks to process"}},
1991 {"cut-DCA-median", VariantType::Float, 3.f, {"Cut on the DCA: abs(DCA-medianDCA)<cut-DCA-median"}},
1992 {"cut-DCA-RMS", VariantType::Float, 3.f, {"Sigma cut on the DCA"}},
1993 {"refX-for-sector", VariantType::Float, 108.475f, {"Reference local x position for the sector information (default centre of IROC)"}},
1994 {"refX-for-outer-ITS", VariantType::Float, 60.f, {"Reference local x position for matching at outer ITS"}},
1995 {"tgl-bins", VariantType::Int, 30, {"Number of tgl bins for time series variables"}},
1996 {"phi-bins", VariantType::Int, 54, {"Number of phi bins for time series variables"}},
1997 {"qPt-bins", VariantType::Int, 18, {"Number of qPt bins for time series variables"}},
1998 {"mult-bins", VariantType::Int, 25, {"Number of multiplicity bins for time series variables"}},
1999 {"mult-max", VariantType::Int, 50000, {"MAximum multiplicity bin"}},
2000 {"threads", VariantType::Int, 4, {"Number of parallel threads"}},
2001 {"max-ITS-TPC-DCAr", VariantType::Float, 0.2f, {"Maximum absolut DCAr value for ITS-TPC tracks"}},
2002 {"max-ITS-TPC-DCAz", VariantType::Float, 10.f, {"Maximum absolut DCAz value for ITS-TPC tracks - larger due to vertex spread"}},
2003 {"max-ITS-TPC-DCAr_comb", VariantType::Float, 0.2f, {"Maximum absolut DCAr value for ITS-TPC tracks to vertex for combined DCA"}},
2004 {"max-ITS-TPC-DCAz_comb", VariantType::Float, 0.2f, {"Maximum absolut DCAr value for ITS-TPC tracks to vertex for combined DCA"}},
2005 {"MIP-dedx", VariantType::Float, 50.f, {"MIP dEdx for MIP/dEdx monitoring"}},
2006 {"time-window-mult-mus", VariantType::Float, 50.f, {"Time window in micro s for multiplicity estimate"}},
2007 {"sqrts", VariantType::Float, 13600.f, {"Centre of mass energy used for downsampling"}},
2008 {"min-tracks-per-vertex", VariantType::Int, 6, {"Minimum number of tracks per vertex required"}},
2009 {"max-dedx-ratio", VariantType::Float, 0.3f, {"Maximum absolute log(dedx(pion)/dedx) ratio"}},
2010 {"max-dedx-region-ratio", VariantType::Float, 0.5f, {"Maximum absolute log(dedx(region)/dedx) ratio"}},
2011 {"sample-unbinned-tsallis", VariantType::Bool, false, {"Perform sampling of unbinned data based on Tsallis function"}},
2012 {"sampling-factor", VariantType::Float, 0.001f, {"Sampling factor in case sample-unbinned-tsallis is used"}},
2013 {"disable-min-bias-trigger", VariantType::Bool, false, {"Disable the minimum bias trigger for skimmed data"}},
2014 {"out-file-unbinned", VariantType::String, "time_series_tracks.root", {"name of the output file for the unbinned data"}},
2015 {"max-occupancy-bins", VariantType::Int, 912, {"Maximum number of occupancy bins"}}}};
2016}
2017
2018} // namespace tpc
2019} // end namespace o2
std::vector< unsigned long > times
CDB Type definitions for TPC.
Wrapper container for different reconstructed object types.
o2d::GlobalTrackID GTrackID
Definition of the TOF cluster.
uint64_t vertex
Definition RawEventData.h:9
int16_t time
Definition RawEventData.h:4
Definition of the FIT RecPoints class.
int32_t i
Helper for geometry and GRP related CCDB requests.
calibrator class for accumulating integrated clusters
bounded_vector< float > bins
Class to store the output of the matching to TOF.
Definition of the parameter class for the detector electronics.
Helper class to extract pressure and temperature.
uint32_t j
Definition RawData.h:0
uint32_t side
Definition RawData.h:0
uint32_t padrow
Definition RawData.h:5
class for performing robust averaging and outlier filtering
Class to parse and query time-dependent TPC sector edge fluctuation intervals.
Definition of the ITS track.
Result of refitting TPC-ITS matched track.
Helper class to extract VDrift from different sources.
Extention of GlobalTrackID by flags relevant for verter-track association.
Referenc on track indices contributing to the vertex, with possibility chose tracks from specific sou...
auto getOrbitResetTimeMS() const
void checkUpdates(o2::framework::ProcessingContext &pc)
bool finaliseCCDB(o2::framework::ConcreteDataMatcher &matcher, void *obj)
static GRPGeomHelper & instance()
void setRequest(std::shared_ptr< GRPGeomRequest > req)
GPUd() value_type estimateLTFast(o2 static GPUd() float estimateLTIncrement(const o2 PropagatorImpl * Instance(bool uninitialized=false)
Definition Propagator.h:178
static mask_t getSourcesMask(const std::string_view srcList)
Static class with identifiers, bitmasks and names for ALICE detectors.
Definition DetID.h:58
void snapshot(const Output &spec, T const &object)
DataAllocator & outputs()
The data allocator is used to allocate memory for the output data.
Cluster class for TOF.
Definition Cluster.h:37
static constexpr unsigned int PADROWS
total number of pad rows
Definition Mapper.h:528
static void requestCCDBInputs(std::vector< o2::framework::InputSpec > &inputs)
float getPressure(const ULong64_t timestamp) const
get pressure for given time stamp in ms
void extractCCDBInputs(o2::framework::ProcessingContext &pc) const
trigger checking for CCDB objects
float getMeanTemperature(const ULong64_t timestamp) const
get mean temperature over A and C side
bool accountCCDBInputs(const o2::framework::ConcreteDataMatcher &matcher, void *obj)
check for new CCDB objects
size_t size() const
Total number of intervals across all runs.
std::vector< std::pair< int, float > > getSectorsAtTime(int run, Long64_t timestampMS) const
void setFromTree(TTree &tree, const int iEntry=0, const char *brName="SectorEdgeFluctuation")
set this object from input tree
size_t getNRuns() const
number of total runs stored
void finaliseCCDB(o2::framework::ConcreteDataMatcher &matcher, void *obj) final
void run(ProcessingContext &pc) final
void init(framework::InitContext &ic) final
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)
\constructor
void endOfStream(EndOfStreamContext &eos) final
static void requestCCDBInputs(std::vector< o2::framework::InputSpec > &inputs, bool laser=true, bool itstpcTgl=true)
void extractCCDBInputs(o2::framework::ProcessingContext &pc, bool laser=true, bool itstpcTgl=true)
const VDriftCorrFact & getVDriftObject() const
bool accountCCDBInputs(const o2::framework::ConcreteDataMatcher &matcher, void *obj)
bool isUpdated() const
pid_constants::ID ID
Definition PID.h:92
static constexpr ID Pion
Definition PID.h:96
GLdouble n
Definition glcorearb.h:1982
GLenum src
Definition glcorearb.h:1767
GLuint buffer
Definition glcorearb.h:655
GLuint GLuint GLfloat weight
Definition glcorearb.h:5477
GLsizei GLsizei GLchar * source
Definition glcorearb.h:798
GLint GLint GLsizei GLint GLenum GLenum type
Definition glcorearb.h:275
GLuint GLfloat * val
Definition glcorearb.h:1582
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t0
Definition glcorearb.h:5034
GLint GLuint mask
Definition glcorearb.h:291
GLsizei GLenum * sources
Definition glcorearb.h:2516
constexpr o2::header::DataOrigin gDataOriginTPC
Definition DataHeader.h:576
uint8_t itsSharedClusterMap uint8_t
constexpr double LHCOrbitMUS
constexpr double LHCBunchSpacingNS
constexpr float TwoPI
Defining ITS Vertex explicitly as messageable.
Definition Cartesian.h:288
std::vector< ConfigParamSpec > ccdbParamSpec(std::string const &path, int runDependent, std::vector< CCDBMetadata > metadata={}, int qrate=0)
std::vector< ConfigParamSpec > Options
o2::tpc::PIDResponse PIDResponse
Definition PIDStudy.cxx:69
o2::track::TrackParCov int int int float int nCl
const bool const int TrackITSInternal< NLayers > & track
int angle2Sector(float phi)
Definition Utils.h:183
float sector2Angle(int sect)
Definition Utils.h:193
uint32_t getFirstTForbit(o2::framework::ProcessingContext &pc)
uint64_t getTimeStamp(o2::framework::ProcessingContext &pc)
uint64_t getRunNumber(o2::framework::ProcessingContext &pc)
const std::unordered_map< CDBType, const std::string > CDBTypeMap
Storage name in CCDB for each calibration and parameter type.
Definition CDBTypes.h:98
constexpr unsigned char SECTORSPERSIDE
Definition Defs.h:40
o2::framework::DataProcessorSpec getTPCTimeSeriesSpec(const bool disableWriter, const o2::base::Propagator::MatCorrType matType, const bool enableUnbinnedWriter, o2::dataformats::GlobalTrackID::mask_t src)
Side
TPC readout sidE.
Definition Defs.h:35
@ A
Definition Defs.h:35
@ C
Definition Defs.h:36
TrackParCovF TrackParCov
Definition Track.h:33
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
static void fillTFIDInfo(o2::framework::ProcessingContext &pc, o2::dataformats::TFIDInfo &ti)
const U & getTrack(int src, int id) const
GlobalIDSet getSingleDetectorRefs(GTrackID gidx) const
gsl::span< const o2::trd::CalibratedTracklet > getTRDCalibratedTracklets() const
GTrackID getTPCContributorGID(GTrackID source) const
std::unique_ptr< o2::trd::RecoInputContainer > inputsTRD
void collectData(o2::framework::ProcessingContext &pc, const DataRequest &request)
gsl::span< const unsigned int > occupancyMapTPC
externally set TPC clusters occupancy map
gsl::span< const o2::trd::Tracklet64 > getTRDTracklets() const
static bool downsampleTsallisCharged(float pt, float factorPt, float sqrts, float &weight, float rnd, float mass=0.13957)
Definition Tsallis.cxx:31
D2: per-track TRD tracklet lookup data.
std::vector< float > mDCAr_comb_A_RMS
DCAr RMS for ITS-TPC track - A-side.
std::vector< float > mTPCSigmaZ2A_RMS
sigmaZ2 RMS at vertex
std::vector< float > mSqrtITSChi2_Ncl_C_Median
sqrt(ITC chi2 / ncl)
ITSTPC_Matching mITSTPCAll
ITS-TPC matching efficiency for ITS standalone + afterburner.
std::vector< float > mITSTPCDeltaP4_C_RMS
RMS of track param TPC - track param ITS-TPC for param 4 - A-side.
std::vector< float > mTPCSigmaZ2C_RMS
sigmaZ2 RMS at vertex
TimeSeries mTSTPC
TPC standalone DCAs.
std::vector< float > mITSTPCDeltaP4_A_Median
track param TPC - track param ITS-TPC for param 4 - A-side
ITSTPC_Matching mITSTPCStandalone
ITS-TPC matching efficiency for ITS standalone.
std::vector< float > mITSTPCDeltaP4_C_Median
track param TPC - track param ITS-TPC for param 4 - A-side
std::vector< float > mITSTPCDeltaP3_A_RMS
RMS of track param TPC - track param ITS-TPC for param 3 - A-side.
std::vector< float > mITS_A_NCl_Median
its number of clusters
std::vector< float > mDCAr_comb_C_Median
DCAr for ITS-TPC track - C-side.
std::vector< float > mSqrtITSChi2_Ncl_A_Median
sqrt(ITC chi2 / ncl)
std::vector< float > mSqrtITSChi2_Ncl_C_RMS
sqrt(ITC chi2 / ncl)
std::vector< float > mDCAz_comb_A_RMS
DCAz RMS for ITS-TPC track - A-side.
std::vector< float > mITSTPCDeltaP2_C_RMS
RMS of track param TPC - track param ITS-TPC for param 2 - A-side.
std::vector< float > mITSTPCDeltaP3_A_Median
track param TPC - track param ITS-TPC for param 3 - A-side
void resize(const unsigned int nTotal)
resize buffer for accumulated currents
std::vector< float > mITSTPCDeltaP2_A_Median
track param TPC - track param ITS-TPC for param 2 - A-side
std::vector< float > mSqrtITSChi2_Ncl_A_RMS
sqrt(ITC chi2 / ncl)
std::vector< float > mITSTPCDeltaP2_C_Median
track param TPC - track param ITS-TPC for param 2 - A-side
std::vector< unsigned int > mOccupancyMapTPC
cluster occupancy map
std::vector< std::pair< int, float > > mSecEdgeFlucCorr
applied sector edge fluctuation correction
std::vector< float > mITSTPCDeltaP4_A_RMS
RMS of track param TPC - track param ITS-TPC for param 4 - A-side.
std::vector< float > mTPCSigmaY2A_Median
sigmaY2 at vertex
std::vector< float > mITSTPCDeltaP3_C_RMS
RMS of track param TPC - track param ITS-TPC for param 3 - A-side.
TimeSeries mTSITSTPC
ITS-TPC standalone DCAs.
std::vector< float > mTPCSigmaY2C_Median
sigmaY2 at vertex
std::vector< float > mTPCSigmaZ2C_Median
sigmaZ2 at vertex
std::vector< float > mITS_C_NCl_RMS
its number of clusters
std::vector< float > mDCAz_comb_A_Median
DCAz for ITS-TPC track - A-side.
std::vector< float > mDCAz_comb_C_RMS
DCAz RMS for ITS-TPC track - C-side.
ITSTPC_Matching mITSTPCAfterburner
ITS-TPC matchin efficiency fir ITS afterburner.
std::vector< float > mTPCSigmaY2C_RMS
sigmaY2 RMS at vertex
std::vector< float > mITSTPCDeltaP3_C_Median
track param TPC - track param ITS-TPC for param 3 - A-side
std::vector< float > mDCAz_comb_C_Median
DCAz for ITS-TPC track - C-side.
std::vector< float > mTPCSigmaZ2A_Median
sigmaZ2 at vertex
std::vector< float > mDCAr_comb_C_RMS
DCAr RMS for ITS-TPC track - C-side.
float mVDrift
drift velocity in cm/us
std::vector< float > mITS_C_NCl_Median
its number of clusters
TimeSeriesdEdx mdEdxQTot
time series for dE/dx qTot monitoring
std::vector< float > mITS_A_NCl_RMS
its number of clusters
std::vector< float > mITSTPCDeltaP2_A_RMS
RMS of track param TPC - track param ITS-TPC for param 2 - A-side.
std::vector< float > mTPCSigmaY2A_RMS
sigmaY2 RMS at vertex
std::vector< float > mDCAr_comb_A_Median
DCAr for ITS-TPC track - A-side.
void setBinning(const int nBinsPhi, const int nBinsTgl, const int qPtBins, const int nBinsMult, float tglMax, float qPtMax, float multMax)
TimeSeriesdEdx mdEdxQMax
time series for dE/dx qMax monitoring
int getIndexInt(int slice=0) const
std::vector< float > mDCAr_C_Median
integrated 1D DCAr for C-side weighted mean in phi/tgl slices
std::vector< float > mDCAz_A_RMS
integrated 1D DCAz for A-side RMS in phi/tgl slices
std::vector< float > mDCAz_C_Median
integrated 1D DCAz for C-side median in phi/tgl slices
int getIndexPhi(const int iPhi, int slice=0) const
std::vector< float > mDCAz_A_Median
integrated 1D DCAz for A-side median in phi/tgl slices
std::vector< float > mDCAr_C_RMS
integrated 1D DCAr for C-side RMS in phi/tgl slices
std::vector< float > mDCAr_A_Median
integrated 1D DCAr for A-side median in phi/tgl slices
int getIndexTgl(const int iTgl, int slice=0) const
std::vector< float > mMIPdEdxRatioQMaxA
ratio of MIP/dEdx - qMax -
std::vector< float > mDCAz_C_RMS
integrated 1D DCAz for C-side RMS in phi/tgl slices
int getIndexqPt(const int iqPt, int slice=0) const
std::vector< float > mDCAr_A_RMS
integrated 1D DCAr for A-side RMS in phi/tgl slices
int getIndexMult(const int iMult, int slice=0) const
std::vector< float > mLogdEdx_A_Median
log(dEdx_exp(pion)/dEdx) - A-side
vec clear()
std::uniform_int_distribution< unsigned long long > distr