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